3

我有一个通用类。它有 2 个构造函数。这些在我组织的代码库中被广泛使用。

class MyClass<T> {
  MyClass() { ... }
  MyClass(T defaultValue) { ... }
}

我想添加一些功能但保持向后兼容。所以我想为每个构造函数引入一个新的布尔可选参数:

class MyClass<T> {
  MyClass(bool someFlag = false) { ... }
  MyClass(T defaultValue, bool someFlag = false) { ... }
}

但是,我已经有一堆用法,其中 T 是布尔值并传递了一个默认值:

class Usage {
  MyClass<bool> Booly = new MyClass<bool>(false);
}

现在,根据重载偏好法则 - 编译器将所有此类构造函数的用法与重载接受联系起来someFlag,因为类型化方法“知道得更好”。虽然在大多数情况下都非常合理,但这显然破坏了我的向后兼容性。

我的问题很简单:是否有可用的语言功能来覆盖默认的重载偏好法则,并将旧的通用重载定义为首选,这样我就不必更改所有这些用法?

当然,这种设计的一个缺点是,每当我想调用第一个重载(只有someFlag参数)时,我都必须按照 C# 4 规范指定一个命名参数。

也欢迎对其他设计提出建议,但请先尝试回答我的问题:)。

4

2 回答 2

1

一般来说?不。

一个特定的...“解决方法”...在您的情况下可能是可以接受的?使可选参数 a bool?,而不是 a bool

new MyClass<bool>(false)会打电话给你的defaultValue超载。

new MyClass<bool>(someFlag: false)将调用另一个重载。

也就是说,如果您有任何现有的new MyClass<bool?>(false)呼叫,这将改变它们

您可以通过创建一个专门用于使您的标志不是布尔值的类来克服这个问题:

public struct FakeBool
{
    private readonly bool val;
    private FakeBool(bool val) { this.val = val; }
    public static implicit operator bool(FakeBool f) { return f.val; }
    public static implicit operator FakeBool(bool f) { return new FakeBool(f); }
}

public MyClass(FakeBool someFlag = default(FakeBool)) { ... }
public MyClass(T defaultValue, FakeBool someFlag = default(FakeBool)) { ... }

var b2 = new MyClass<bool>(true);            // calls two-argument constructor
var b1 = new MyClass<bool>(someFlag: true); // calls one-argument constructor

但这越来越愚蠢。(另外,我不知道如何获得默认值true - 任何想法,有人吗?)

于 2012-10-03T15:02:47.007 回答
0

假设您可以拥有一个Initialize()可以从每个构造函数调用的类型方法,那么最好的办法是拥有三个构造函数:

MyClass() { Initialize(null, false); }
MyClass(T default, bool someFlag = false) { Initialize(default, someFlag); }
MyClass(bool someFlag)
{
   if (typeof(T) == typeof(bool))  Initialize(someFlag, false);
   else Initialize(null, someFlag);
}

private Initialize(T default, bool someFlag)
{ 
   // Do whatever
}
于 2012-10-05T13:54:49.097 回答