我有一个通用类。它有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规范指定一个命名参数。
也欢迎对其他设计的建议,但请先尝试回答我的问题:)。
答案 0 :(得分:1)
一般情况下?否。
具体......“解决方法”......在您的情况下可能会接受?将可选参数设为bool?
,而不是bool
。
new MyClass<bool>(false)
会调用defaultValue
超载。
new MyClass<bool>(someFlag: false)
将调用另一个重载。
也就是说,如果您有任何现有的new MyClass<bool?>(false)
来电,则会改为他们。
你可以通过创建一个专门用于使你的旗帜不是bool的类来克服 this :
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 - 任何想法,任何人?)
答案 1 :(得分: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
}