我有以下c#类:
class A : Object
{
foo() {}
}
class B : Object
{
foo() {}
}
我想写一个适用于两者的通用方法:
void bar<T>(T t)
{
t.foo();
}
这不会编译抱怨foo()不是T的成员。我可以为T派生一个约束来从其中一个类派生:
void bar<T>(T t) where T : A
但我怎么能同时拥有它呢?
答案 0 :(得分:5)
简单地说你不能。但是有几种方法可以解决这个问题。
最常见的是使用界面。说IMyType
interface IMyType { void foo(); }
class A : IMyType ...
class B : IMyType ...
void bar<T>(T t) where 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());
答案 1 :(得分:2)
您应该定义一个界面:
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();
}
答案 2 :(得分:1)
定义包含 foo 方法的接口,并使用A&amp;类; B实现那个接口。然后在泛型类型上定义接口约束。
答案 3 :(得分:1)
除非你:
,否则你不能这样做我更喜欢界面,因为它不会强迫你分享行为:
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
}
答案 4 :(得分:1)
这可以在.NET 4.0中使用dynamic
。
void bar(dynamic t)
{
t.foo();
}
答案 5 :(得分:0)
你为什么要这个通用?只是重载方法。
void bar(A a) { a.Foo(); }
void bar(B b) { b.Foo(); }
泛型是存在的,因此您可以制作潜在的无限bar()
方法。