C# 泛型:如何从两个类中的一个派生?

C# 泛型:如何从两个类中的一个派生?,c#,generics,C#,Generics,我有以下c#类课程: 我想编写一个适用于以下两种情况的通用方法: void bar<T>(T t) { t.foo(); } void bar(T) { t、 foo(); } 如果foo()不是T的成员,则不会进行编译。我可以为T添加一个约束,使其派生自以下其中一个类: void bar<T>(T t) where T : A 空心条(T),其中T:A 但是我怎样才能同时使用它呢?定义一个包含foo方法的接口,并让类A和B实现该接口。然后在泛型类型上定义接口

我有以下c#类课程:

我想编写一个适用于以下两种情况的通用方法:

void bar<T>(T t)
{
  t.foo();
}
void bar(T)
{
t、 foo();
}
如果foo()不是T的成员,则不会进行编译。我可以为T添加一个约束,使其派生自以下其中一个类:

void bar<T>(T t) where T : A
空心条(T),其中T:A

但是我怎样才能同时使用它呢?

定义一个包含foo方法的接口,并让类A和B实现该接口。然后在泛型类型上定义接口约束。

简单地说,您不能。不过,有几种方法可以解决这个问题

最常见的是使用接口。说
IMyType

interface IMyType { void foo(); }
class A : IMyType ...
class B : IMyType ...

void bar<T>(T t) where T : IMyType {
  t.Foo();
}
接口IMyType{void foo();}
A类:IMyType。。。
B类:IMyType。。。
空心条(T),其中T:IMyType{
t、 Foo();
}
这是一个有点重的问题,尽管它需要对解决方案进行元数据更改。更便宜的方法是提供一个lambda表达式来调用适当的函数

void bar<T>(T t, Action doFoo) {
  ...
  doFoo();
}

var v1 = new A();
var v2 = new B();
bar(v1, () => v1.Foo());
bar(v2, () => v2.Foo());
void条(T T,Action doFoo){
...
doFoo();
}
var v1=新的A();
var v2=新的B();
bar(v1,()=>v1.Foo());
bar(v2,()=>v2.Foo());

除非您:

  • 从基类派生
  • 从接口派生
  • 我更喜欢界面,因为它不会强迫你分享行为:

    public interface IHasFoo
    {
        void foo();
    }
    
    public class B : IHasFoo // you don't need to explicitly subclass object
    {
        public void foo()
        {
        }
    }
    
    public class A : IHasFoo // you don't need to explicitly subclass object
    {
        public void foo()
        {
        }
    }
    
    void bar<T>(T t) where T : IHasFoo
    {
        t.foo(); // works
    }
    
    公共接口IHasFoo
    {
    void foo();
    }
    public类B:IHasFoo//您不需要显式地将对象子类化
    {
    公共图书馆
    {
    }
    }
    public class A:IHasFoo//您不需要显式地将对象子类化
    {
    公共图书馆
    {
    }
    }
    空心条(T),其中T:IHasFoo
    {
    t、 foo();//有效
    }
    
    您应该定义一个接口:

    interface IFoo
    {
       void foo();
    }
    
    
    class A : IFoo
    {
       public void foo() {}
    }
    
    class B : IFoo
    {
       public void foo() {}
    }
    
    以及您的通用方法:

    void bar<T>(T t) where T:IFoo
    {
      t.foo();
    }
    
    void bar(T)其中T:IFoo
    {
    t、 foo();
    }
    
    这在.NET 4.0中使用
    动态
    是可能的

    void bar(dynamic t)
    {
      t.foo();
    }
    

    你为什么要把它变成普通的?只需重载该方法

     void bar(A a) { a.Foo(); }
     void bar(B b) { b.Foo(); }
    

    泛型的存在是为了让您可以创建潜在的无限
    bar()
    方法。

    几乎不回避这个问题。如果这是一个用例,那么有一个通用的方法仍然有意义吗?为什么不简单地实现A和B的接口“IFoo”,并将该方法声明为voidbar(ifoof){f.foo();}
     void bar(A a) { a.Foo(); }
     void bar(B b) { b.Foo(); }