C# – 如何引用一个引用任何实现一组接口的对象的类型?

我怎样才能有一个类型引用引用任何实现一组接口的对象?

例如,我可以使用这样的generics类型:

Java的:

public class Foo { } 

C#

 public class Foo where T : A, B { } 

这就是如何拥有类范围的generics类型。 但是,我想简单地拥有一个数据成员,它引用任何扩展给定接口集的对象。

例:

 public class Foo { protected  object; public void setObject( object) { this.object = object; } } 

如果有可能有这种类型的语法,我怎么能在Java和C#中做到这一点?


我意识到我可以创建另一个扩展所有所需接口的接口。 但是,我不认为这是最优的,因为它不必要地添加另一种类型,其唯一目的是绕过语法。 虽然这是一个非常小的问题,但就优雅而言,它有点令人痛苦。

在C#中,您可以使用元组将值存储为一种叠加

 public class Foo { private Tuple junction; public void SetValue(T value) where T : IA, IB { junction = Tuple.Create(value, value); } } 

您还可以使用专门的类来强制执行两个值引用同一对象的约束:

 public class Junction { public IA A { get; private set; } public IB B { get; private set; } private Junction() { } public static Junction Create(T value) where T: IA, IB { return new Junction { A = value, B = value }; } } public class Foo { private Junction junction; public void SetValue(T value) where T : IA, IB { junction = Junction.Create(value); } } 

在Java中,通配符可以简化一些事情:

 class Junction { private final E value; public Junction(E value) { this.value = value; } public E getValue() { return value; } } class Foo { private Junction junction; public  void setValue(E value) { junction = new Junction(value); } } 

或者您可以将别名设为相同的值(C#,但也适用于Java):

 public class Foo { private IA a; private IB b; public void SetValue(T value) where T : IA, IB { a = value; b = value; } } 

经过2年的不活动,我的Java变得有点生疏了。

这是我的C#方法:(有关完整工作示例,请参阅https://ideone.com/N20xU )

 public class Foo { private IInterface1 _object; // just pick one public void setObject(T obj) where T : IInterface1, IComparable, IEtcetera { // you now *know* that object supports all the interfaces // you don't need the compiler to remind you _object = obj; } public void ExerciseObject() { // completely safe due to the constraints on setObject IEtcetera itf = (IEtcetera) _object; // .... } 

据我所知,你不能创建一个带有约束的变量,你只能创建一个给定类型的变量。 类型有约束。 这意味着您必须定义具有所需约束的类型,然后使用该类型创建变量。

这对我来说似乎是合乎逻辑的,我不明白为什么你觉得必须为你需要的东西定义一个类型“很难”。

简单地将约束声明为私有接口我没有看到任何问题:

 class Foo { interface R : I1, I2 { } R _object; void setObject(R r) { _object = r; } } 

这是我能想到的最好的(但仍然不是最佳解决方案)

 public class Foo { private TypeWrapper _object; public void setObject(T obj) where T : IInterface1, IInterface2 { _object = new TypeWrapper(); _object.SetObject(obj); var val = _object.Get(h => hc); Console.WriteLine(val); _object.Do(h => hc = 25); val = _object.Get(h => hc); Console.WriteLine(val); _object.Do(h => h.someF()); } } public class TypeWrapper { private Object m_Obj; public void SetObject(T obj) where T : TType, TTypeTwo { m_Obj = obj; } public T Get(Func action) { return (T)action((TType)m_Obj); } public T Get(Func action) { return (T)action((TTypeTwo)m_Obj); } public void Do(Action action) { action((TTypeTwo)m_Obj); } public void Do(Action action) { action((TType)m_Obj); } } public class myClass : IInterface1, IInterface2 { public int t {get;set;} public int c {get;set;} public void someF() { Console.WriteLine("Fired"); } } public interface IInterface1 { int t { get;set;} void someF(); } public interface IInterface2 { int c { get;set; } } 

您将不得不通过Get和Do方法处理该对象,但如果接口发生更改,它将与intellisense一起使用并抛出编译时错误。