我希望能够在C#基类中有一个方法,可以在几个派生类的对象上调用,返回对象本身,让CLR知道对象的实际类型 - 即适当的派生类型. 有人可以建议一种方法吗? 其他当然,还有C#没有的返回类型协方差.
像这样的东西,除了Method()返回类型应该是派生类的类型,而不是基类:
public abstract class Base {
public Base Method() { return this; }
}
public class Derived1: Base { ... }
public class Derived2: Base { ... }
public class Main {
public static int Main() {
Derived1 d1 = new Derived1();
Derived1 x = d1.Method();
Derived2 d2 = new Derived2();
Derived2 y = d2.Method();
}
}
Run Code Online (Sandbox Code Playgroud)
我只能想到两种方法来完成这项工作,我不喜欢其中任何一种:
将Method()的结果转换为期望的类型(例如,Derived1 x = (Derived) d1.Method();).但是施法者是魔鬼的工具,此外,该方法的目的是返回一个Derived1或Derived2或......,而不是一个Base.
Method()在基类中声明为抽象,并在每个派生类中单独实现它.但这与分解常用方法的想法完全相反.的Method()将是在每种情况下,除了它的返回类型相同.
Jon*_*eet 11
好的,我误解了这个问题.我以为OP 确实想要覆盖这个方法.显然不是,所以泛型是前进的方向:
public abstract class Base<T> where T : Base<T>
{
public T Method()
{
return (T) (object) this;
}
}
public class Derived1 : Base<Derived1>
{
}
Run Code Online (Sandbox Code Playgroud)
还有一个演员阵容,但据我所知,这是不可避免的.你几乎肯定也想在构造函数中检查它:
public Base()
{
if (this as T == null)
{
// throw some exception
}
}
Run Code Online (Sandbox Code Playgroud)
它很难看,但它会起作用......丑陋只限于基类.
原始答案
一种方法是放入Method通用接口并明确实现它:
public interface IFoo<T> {
T Method();
}
public abstract class Base : IFoo<Base>
{
Base IFoo<Base>.Method()
{
return this;
}
}
public class Derived1 : IFoo<Derived1>
{
public Derived1 Method()
{
// If you need to call the base version, you'll
// need ((IFoo<Base>)this).Method()
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
这不好,但它会起作用......在可能的情况下,我想我会尽量避免需要它,说实话.(是的,我在实现协议缓冲时遇到过类似的情况.这很烦人.)
smo*_*oak 11
我相信你可以dynamic在C#4.0上使用关键字:
public abstract class Base {
public dynamic Method() { return this; }
}
public class Derived1: Base { ... }
public class Derived2: Base { ... }
public class Main {
public static int Main() {
Derived1 d1 = new Derived1();
Derived1 x = d1.Method();
Console.WriteLine(x.GetType()); // outputs Derived1
Derived2 d2 = new Derived2();
Derived2 y = d2.Method();
Console.WriteLine(y.GetType()); // outputs Derived2
}
}
Run Code Online (Sandbox Code Playgroud)
似乎有很多方法可以实现这一点:也可以使用扩展方法.
这样做的好处是允许你使用你不拥有的类,而你只需要执行一次,而不是每次派生/基类.这将完全符合您的要求.
public class BaseClass
{
}
public class DerivedClass: BaseClass
{
}
public static class BaseClassHelpers
{
public static T Method<T>(this T b) where T : BaseClass
{
return b;
}
}
Run Code Online (Sandbox Code Playgroud)
正在使用:
DerivedClass d = new DerivedClass();
DerivedClass dd = d.Method();
Console.WriteLine(dd.GetType());
Run Code Online (Sandbox Code Playgroud)
导致控制台:
DerivedClass
Run Code Online (Sandbox Code Playgroud)
还有泛型但没有界面:
public abstract class Base<T> where T : Base<T>
{
public virtual T Method()
{
return (T) this;
}
}
public class Derived1 : Base<Derived1>
{
public override Derived1 Method()
{
return base.Method();
}
}
public class Derived2: Base<Derived2> { }
public class Program {
public static int Main() {
Derived1 d1 = new Derived1();
Derived1 x = d1.Method();
Derived2 d2 = new Derived2();
Derived2 y = d2.Method();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6939 次 |
| 最近记录: |