我正在重构具有以下类的旧库:
public class Template //Old one
{
public double Value { get; set; }
}
现在最好提供更大的灵活性以允许用户定义的Value
类型。因此,我将Template
更改为通用类:
public class Template<T>
{
public T Value { get; set; }
}
此更改打破了其他旧Template
类的用法,因此我尝试通过以下方式添加向后兼容性(允许其他人以旧方式使用我的库):
public class Template: Template<double> { }
但是它也需要在库中进行很多更改。尤其是在使用旧的Template
的地方,例如:
public class AnotherClassInLibrary<T>
{
public Template<T> API() {...}
}
public class AnotherClassInLibrary : AnotherClassInLibrary<double>
{
// This class is also defined for the old way of using the library
public Template API()
{
return base.API();
// Error here: Template<double> cannot be implicitly convert to Template.
}
}
问题来了:新的Template
是从Template<double>
继承的,因此在这里强制转换不是一个好方法。有没有变通的方法来保持AnotherClassInLibrary
向后兼容,而又不会两次重写API()
代码?
P.S。我真的希望C#在C ++中有类似typedef
的东西。但是the answer is NO。
答案 0 :(得分:0)
即使您的Template
类是从Template<double>
继承的,也不一样。考虑到您将按照以下方式更改Template
的定义:
public class Template : Template<double>
{
public int AddedMember { get; set; }
}
现在,您尝试执行前面的代码。您正在尝试将具有某些属性的类转换为具有更多属性的类-您将访问内存中不正确的位置!
您总是可以将一个类转换为其基类,因为驱动类包含所有基类的成员。因此,不需要显式转换。但是,当您尝试将基类转换为驱动类时,仅当基类变量指向驱动类的实例时,转换才会成功,因此,驱动类的所有成员都存在。如果否,则会在运行时引发InvalidCastException
。因此,必须进行显式强制转换(因为使用显式强制转换的指导原则之一是,如果强制转换可能失败,则使用显式强制转换)。
因此,如果您将代码更改为变量a(类型为Template<double>
),则转换将成功:
Template a = new Template(); 模板b =(模板)a; //没有异常会抛出
最后一个代码将成功,因为变量a
指向Template
的实例(而不是Template<double>
的实例),因此我们确保(在运行时){ {1}}存在,不会发生错误。
在您说完您的要求之后,我可以为您提供帮助。你想要什么?您想启用Template
到Template
的转换-这可以通过user-defined conversions进行。
但是,不允许在驱动类和基类之间进行自定义转换。因此,有两种解决方案:
1)Template<double>
不会继承自Template
,如下所示:
Template<double>
2)您将不定义自定义转换,而是定义一个常规方法(我定义了一个构造函数):
public class Template<T>
{
public T Value { get; set; }
}
public class Template
{
public double Value { get; set; }
public static explicit operator Template(Template<double> generic) // Or implicit instead of explicit
{
return new Template { Value = generic.Value };
}
}
var generic = new Template<double> { Value = 1234.56 };
var nongeneric = (Template)generic; // Or Template nongeneric = generic; if the conversion defined as implicit