将泛型类转换为其继承类

我正在重构一个旧库,其中包含以下类:


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.

    }

}

所以问题来了: newTemplate是从 继承的Template<double>,所以在这里转换不是一个好的/工作实践。有没有办法在AnotherClassInLibrary不重写API()代码两次的情况下保持向后兼容?


PS 我真的希望 C# 有类似typedefC++ 的东西。但答案是否定的。


明月笑刀无情
浏览 206回答 1
1回答

慕丝7291255

即使你的Template类继承自Template<double>,它也不一样。考虑您将更改的定义Template如下:public class Template : Template<double>{&nbsp; &nbsp; public int AddedMember { get; set; }}现在,您尝试执行前面的代码。您正在尝试将具有某些属性的类转换为具有更多属性的类 - 您将访问内存中不正确的位置!您始终可以将类转换为其基类,因为驱动类包含所有基类的成员。因此,不需要显式转换。但是,当您尝试将基类转换为驱动类时,只有当基类变量指向驱动类的实例时,转换才会成功,因此,驱动类的所有成员都存在。如果否,InvalidCastException则在运行时抛出遗嘱。因此,需要显式转换(因为使用显式转换的准则之一是在转换可能失败时使用显式转换)。因此,如果您将代码更改为变量 a(类型Template<double>),则转换将成功:Template<double> a = new Template();Template b = (Template)a; // No exception will thrown最后的代码会成功,因为变量a指向的Template(而不是Template<double>)的实例,所以我们确定(在运行时)所有的成员Template都存在并且不会发生错误。编辑:你说出你的要求后,我可以帮你。你想要什么?您想启用“模板”到“模板”的转换 - 这可以通过 [用户定义的转换](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions -运营商/转换运营商)。但是,不允许在驱动类和基类之间进行自定义转换。所以,有两种解决方案:Template不会继承自Template<double>,如下所示:&nbsp; &nbsp; public class Template<T>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public T Value { get; set; }&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; public class Template&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public double Value { get; set; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; public static explicit operator Template(Template<double> generic) // Or implicit instead of explicit&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new Template { Value = generic.Value };&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; var generic = new Template<double> { Value = 1234.56 };&nbsp; &nbsp; var nongeneric = (Template)generic; // Or Template nongeneric = generic; if the conversion defined as implicit您不会定义自定义转换,而是定义一个常规方法(我定义了一个构造函数):&nbsp; &nbsp; public class Template<T>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public T Value { get; set; }&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; public class Template : Template<double>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public Template(Template<double> generic)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Value = generic.Value;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; var generic = new Template<double> { Value = 1234.56 };&nbsp; &nbsp; var nongeneric = new Template(generic);
打开App,查看更多内容
随时随地看视频慕课网APP