代码之家  ›  专栏  ›  技术社区  ›  Jean-Bernard Pellerin

C#泛型-我能从两个选择中选择一个吗?

  •  20
  • Jean-Bernard Pellerin  · 技术社区  · 14 年前

    Class A {...}
    
    Class B : A  {...}
    
    Class C : A {...}
    

    我现在拥有的是

    Class D<T> where T : A {...}
    

    但我想要这种形式的东西

    Class D<T> where T in {B,C}
    

    这是由于一些奇怪的行为,我不负责其中B和C有共同的方法,而这些方法不在A中,但如果能够在t上的D中调用它们就更好了。

    7 回复  |  直到 13 年前
        1
  •  24
  •   Grzenio    14 年前

    您需要为B和C中的常用方法定义一个接口(我们称之为Ibc),使B和C实现这个接口,然后您可以编写:

    Class D<T> where T : A, Ibc {...}
    
        2
  •  9
  •   Dan Tao    14 年前

    这是不可能的。

    正如其他人所建议的那样,您可以定义一个接口并在这两种语言中实现它 B C .

    如果这不是一个选项(例如,如果这些类超出了您的控制范围),那么我的建议是:首先,从一个抽象类开始,它包含了您可以用任何方法实现的所有功能 T 源自 A . 然后假设你有一些方法可以同时适用于这两种情况 B C 这不属于 A . 在 D 您可以使这些抽象方法由子类实现:

    public abstract class D<T> where T : A
    {
        protected T _member;
    
        public void DoSomethingAllTsCanDo()
        {
            _member.DoSomething();
        }
    
        public abstract void DoSomethingOnlyBAndCCanDo();
    }
    

    然后可以从每个类型的基类继承 B C

    public class DB : D<B>
    {
        public override void DoSomethingOnlyBAndCCanDo()
        {
            _member.DoSomethingOnlyBCanDo();
        }
    }
    
    public class DC : D<C>
    {
        public override void DoSomethingOnlyBAndCCanDo()
        {
            _member.DoSomethingOnlyCCanDo();
        }
    }
    
        3
  •  6
  •   Kobi    14 年前

    首先,如果B和C有共同的方法,这是一个设计缺陷,他们不共享一个接口。也就是说,即使不需要访问B和C,也可以修复这个问题。

    public class A
    {
    }
    public class B : A
    {
        public void Start() { }
    }
    public class C : A
    {
        public void Start() { }
    }
    

    您可以创建一个公共接口:

    public interface IStartable
    {
        void Start();
    }
    

    并将其用于B和C的派生类:

    public class BetterB : B, IStartable
    {
    }
    public class BetterC : C, IStartable
    {
    }
    

    D<T>

        4
  •  3
  •   Anthony Potts    14 年前

    B和C实现相同的接口吗?那可能是一条更好的路线。

        5
  •  2
  •   Community kfsone    7 年前

    一些选项:

    1. 制作接口 IderivedFromA 包含来自 B C .
    2. D T dynamic 并动态调用这些方法
    3. 测试您是否处理 B C 、播放和呼叫
      将由编译器检查,并且可以从.NET2
    4. The Dan Tao answer :创建的特定实现 D<T> 对于 B C ,这些方法可以从 B C 直接(我自己没想到这个)。
      只有当“用户源”知道它正在处理 C A 使用 D<A> . 相反,它应该使用 DB DC . 但我认为是这样,否则你不需要泛型。
        6
  •  1
  •   Dennis    14 年前
        7
  •  0
  •   BlueRaja - Danny Pflughoeft    14 年前

    (除非您愿意使用 dynamic 是显式检查 B / C 和演员。