如何在C#中使用派生返回类型覆盖方法? [英] How to override method with derived return type in C#?

查看:102
本文介绍了如何在C#中使用派生返回类型覆盖方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用派生类类型覆盖虚方法。目前最好的方法是什么?到目前为止,我发现了两种方法:

I want to override a virtual method with a derived class type. What's the current best way to do this? So far I've found two approaches:


  1. 使用 abstract base <$每个派生类型的c $ c> class ;使用 protected 方法桥接。

  2. 使用 protected 实现 public accessor。

  1. Use an abstract base class for each derived type; bridge with protected methods.
  2. Use a protected implementation with a public accessor.

基本情况(未实施解决方案,克隆始终返回基本类型 A1 ):

Base case (no solution implemented, Clone always returns base type A1):

    public class A1
    {
        public int X1 { get; set; }
        public A1(int x1) { this.X1 = x1; }
        public virtual A1 Clone() { return new A1(X1); }
    }
    public class A2 : A1
    {
        public int X2 { get; set; }
        public A2(int x1, int x2) : base(x1)  { this.X2 = x2; }
        public override A1 Clone() { return new A2(X1, X2); }  //can't explicitly return A2
    }
    public class A3 : A2
    {
        public int X3 { get; set; }
        public A3(int x1, int x2, int x3) : base(x1, x2) { this.X3 = x3; }
        public override A1 Clone() { return new A3(X1, X2, X3); }  //can't explicitly return A3
    }

解决方案#1(使用 abstract 每个派生类型的基类, protected bridge):

Solution #1 (using abstract base classes for each derived type with protected bridges):

    public class B1
    {
        public int X1 { get; set; }
        public B1(int x1) { this.X1 = x1; }
        public virtual B1 Clone() { return new B1(X1); }
    }
    public abstract class B2_Base : B1
    {
        public B2_Base(int x1) : base(x1) { }
        public sealed override B1 Clone() { return this.CloneAsB1(); }
        protected abstract B1 CloneAsB1();
    }
    public class B2 : B2_Base
    {
        public int X2 { get; set; }
        public B2(int x1, int x2) : base(x1) { this.X2 = x2; }
        protected sealed override B1 CloneAsB1() { return this.Clone(); }
        public new virtual B2 Clone() { return new B2(X1, X2); }  //CAN explicitly return B2
    }
    public abstract class B3_Base : B2
    {
        public B3_Base(int x1, int x2) : base(x1, x2) { }
        public sealed override B2 Clone() { return this.CloneAsB2(); }
        protected abstract B2 CloneAsB2();
    }
    public class B3 : B3_Base
    {
        public int X3 { get; set; }
        public B3(int x1, int x2, int x3) : base(x1, x2) { this.X3 = x3; }
        protected sealed override B2 CloneAsB2() { return this.Clone(); }
        public new virtual B3 Clone() { return new B3(X1, X2, X3); }  //CAN explicitly return B3
    }

解决方案#2(使用 protected 使用 public accessors实现:

Solution #2 (using protected implementation with public accessors):

    public class C1
    {
        public int X1 { get; set; }
        public C1(int x1) { this.X1 = x1; }
        public C1 Clone() { return this.CloneImplementation(); }
        protected virtual C1 CloneImplementation() { return new C1(X1); }
    }
    public class C2 : C1
    {
        public int X2 { get; set; }
        public C2(int x1, int x2) : base(x1) { this.X2 = x2; }
        public new C2 Clone() { return this.CloneImplementation() as C2; }  //trusts CloneImplementation to return a C2
        protected override C1 CloneImplementation() { return new C2(X1, X2); }
    }
    public class C3 : C2
    {
        public int X3 { get; set; }
        public C3(int x1, int x2, int x3) : base(x1, x2) { this.X3 = x3; }
        public new C3 Clone() { return this.CloneImplementation() as C3; }  //trusts CloneImplementation to return a C3
        protected override C1 CloneImplementation() { return new C3(X1, X2, X3); }
    }

据我所知,解决方案#1是最严格的方法,但每个派生的类 abstract base class >想要替换基础的返回类型。

So far as I can tell, Solution #1 is the most rigorous approach, but it requires an abstract base class for each derived class which wants to replace the base class's return type.

解决方案#2更简单易懂,但它在内部类型安全方面有一个小小的突破。具体来说,每个派生类型的 public 访问器都信任其 protected 方法将返回正确的类型。所以可以有一个内部类型断开,例如:

Solution #2's simpler and easier to understand, but it has a small break in internal type safety. Specifically, each derived type's public accessor trusts that its protected method will return the correct type. So it's possible to have an internal type disconnect, e.g.:

    public class C2 : C1
    {
        public int X2 { get; set; }
        public C2(int x1, int x2) : base(x1) { this.X2 = x2; }
        public new C2 Clone() { return this.CloneImplementation() as C2; }  //trusts CloneImplementation to return a C2
        protected override C1 CloneImplementation() { return new C1(X1); }
    }

是否有一个正确的(普遍接受的)最佳实践来覆盖派生方法类型?

Is there a correct (generally accepted) best practice for overriding methods with derived types?

推荐答案

您可以使基类通用:

public abstract class Base<TDerived> where TDerived : Base {
  public abstract TDerived Clone();
}

public class Derived1 : Base<Derived1> {
  public override Derived1 Clone() { ... }
}

public class Derived2 : Base<Derived2> {
  public override Derived2 Clone() { ... }
}

然而,这让我想知道有一个共同的基类是多么有用。也许Derived1和Derived2的Clone实现不需要是通用接口的一部分。

However this makes me wonder how useful having a common base class is. Perhaps the Clone implementations of Derived1 and Derived2 don't need to be part of a common interface.

这篇关于如何在C#中使用派生返回类型覆盖方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆