[英]C# - How can I have an type that references any object which implements a set of Interfaces?
我怎样才能有一个类型引用引用任何实现一组接口的对象?
例如,我可以使用这样的泛型类型:
Java的:
public class Foo<T extends A & B> { }
C#
public class Foo<T> where T : A, B { }
这就是如何拥有类范围的泛型类型。 但是,我想简单地拥有一个数据成员,它引用任何扩展给定接口集的对象。
例:
public class Foo
{
protected <? extends A, B> object;
public void setObject(<? extends A, B> object)
{
this.object = object;
}
}
如果有可能有这种类型的语法,我怎么能在Java和C#中做到这一点?
我意识到我可以创建另一个扩展所有所需接口的接口。 但是,我不认为这是最优的,因为它不必要地添加另一种类型,其唯一目的是绕过语法。 虽然这是一个非常小的问题,但就优雅而言,它有点令人痛苦。
经过2年的不活动,我的Java变得有点生疏了。
这是我的C#方法:(有关完整工作示例,请参阅https://ideone.com/N20xU )
public class Foo
{
private IInterface1 _object; // just pick one
public void setObject<T>(T obj)
where T : IInterface1, IComparable<T>, 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<T>
IEtcetera itf = (IEtcetera) _object;
// ....
}
据我所知,你不能创建一个带有约束的变量,你只能创建一个给定类型的变量。 该类型具有约束。 这意味着您必须定义具有所需约束的类型,然后使用该类型创建变量。
这对我来说似乎是合乎逻辑的,我不明白为什么你觉得必须为你需要的类型定义一个“无法”。
在C#中,您可以使用元组将值存储为一种叠加 :
public class Foo {
private Tuple<IA, IB> junction;
public void SetValue<T>(T value) where T : IA, IB {
junction = Tuple.Create<IA, IB>(value, value);
}
}
您还可以使用专门的类来强制执行两个值引用同一对象的约束:
public class Junction {
public IA A { get; private set; }
public IB B { get; private set; }
private Junction() { }
public static Junction Create<T>(T value) where T: IA, IB {
return new Junction {
A = value,
B = value
};
}
}
public class Foo {
private Junction junction;
public void SetValue<T>(T value) where T : IA, IB {
junction = Junction.Create(value);
}
}
在Java中,通配符将简化事情有点 :
class Junction<E extends A & B> {
private final E value;
public Junction(E value) {
this.value = value;
}
public E getValue() {
return value;
}
}
class Foo {
private Junction<?> junction;
public <E extends A & B> void setValue(E value) {
junction = new Junction<E>(value);
}
}
或者您可以将别名设为相同的值(C#,但也适用于Java):
public class Foo {
private IA a;
private IB b;
public void SetValue<T>(T value) where T : IA, IB {
a = value;
b = value;
}
}
简单地将约束声明为私有接口我没有看到任何问题:
class Foo
{
interface R : I1, I2 { }
R _object;
void setObject(R r) { _object = r; }
}
这是我能想到的最好的(但仍然不是最佳解决方案)
public class Foo
{
private TypeWrapper<IInterface1,IInterface2> _object;
public void setObject<T>(T obj)
where T : IInterface1, IInterface2
{
_object = new TypeWrapper<IInterface1, IInterface2>();
_object.SetObject(obj);
var val = _object.Get(h => h.c);
Console.WriteLine(val);
_object.Do(h => h.c = 25);
val = _object.Get(h => h.c);
Console.WriteLine(val);
_object.Do(h => h.someF());
}
}
public class TypeWrapper<TType, TTypeTwo>
{
private Object m_Obj;
public void SetObject<T>(T obj) where T : TType, TTypeTwo
{
m_Obj = obj;
}
public T Get<T>(Func<TType, T> action)
{
return (T)action((TType)m_Obj);
}
public T Get<T>(Func<TTypeTwo, T> action)
{
return (T)action((TTypeTwo)m_Obj);
}
public void Do(Action<TTypeTwo> action)
{
action((TTypeTwo)m_Obj);
}
public void Do(Action<TType> 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一起使用并抛出编译时错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.