C# 泛型:如何从两个类中的一个派生?
我有以下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实现该接口。然后在泛型类型上定义接口
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(); }