C# 编译时检查值以实现多个接口
假设我想表达“一个方法,它期望一个对象实现接口IFoo和IBar”。比如:C# 编译时检查值以实现多个接口,c#,types,interface,C#,Types,Interface,假设我想表达“一个方法,它期望一个对象实现接口IFoo和IBar”。比如: void Method(IFoo+IBar param); 我如何用C#来表达这一点? (有句法结构吗?或者是一个好的习语?) 企图 引入一个接口: interface IFooBar : IFoo, IBar {} void Method(IFooBar param); 这太糟糕了,我甚至想到它都很后悔:-)乍一看还行,但可悲的是,它悄悄地引入了一种不应该存在的依赖 IFooBar存在的唯一原因是成为方法接口的
void Method(IFoo+IBar param);
我如何用C#来表达这一点?
(有句法结构吗?或者是一个好的习语?)
企图 引入一个接口:
interface IFooBar : IFoo, IBar {}
void Method(IFooBar param);
这太糟糕了,我甚至想到它都很后悔:-)乍一看还行,但可悲的是,它悄悄地引入了一种不应该存在的依赖
IFooBar
存在的唯一原因是成为方法
接口的一部分。因此,任何要用作方法
参数的对象类都必须知道该方法(以及该接口)存在,否则情况就不会如此。所有实现IFoo和IBar的类都需要修改以实现IFooBar(可能需要了解一个新的程序集)——这是非常不切实际的,如果我们不能修改它们,甚至是不可能的
不必要的依赖=不可能
变通办法
放弃静态键入:
void Method(object param)
{
if (!param is IFoo)
throw new ArgumentException("IFoo not supported", "param");
if (!param is IBar)
throw new ArgumentException("IBar not supported", "param");
// ...
}
(或者:在签名中定义一种类型,并动态检查其他类型-如果其中一种类型最重要,但更容易混淆,则更好)
工作正常,但在运行时(无编译时检查)。迫切需要一个医生(每个人都要读)
也仅适用于函数参数。如果我试着在一个字段上使用它,代码会被大量的类型转换填充
这种情况的真实案例?例如
IList
+INotifyCollectionChanged
公共void somethod(T参数),其中T:IFoo,IBar
public void someMethod<T>(T param) where T : IFoo, IBar
{...}
{...}
我的一个朋友曾经问埃里克·利珀特一个非常类似的问题,他的回答是:
问:C#不允许通过声明变量有什么原因吗
多接口
答:假设我们将其注释为{IFoo,IBar}
问题比声明变量更大。基本上你是
表示要将变量的约束从“
变量必须是给定类型的“to”变量必须是所有
若干特定类型”。但为什么要停留在变量上呢?如果是这样的话
一个变量的约束,那么它应该是一个类型,句点。你
应该能够说:
List< { IFoo, IBar } > myList; Or
等等。半途而废是没有意义的
这将是类型系统的主要扩展。我们想
支持所有托管语言,而不仅仅是C#和VB。这是
您希望在版本中进入框架的功能类型
一,;做出如此重大的改变既昂贵又困难
当你有四个版本并且拥有数十亿条客户线时
必须继续工作的代码
我自己也经常想要这个功能;我同意这是一个好主意
功能,但我认为现在添加它太贵了。下一个
设计新类型系统时,请从
开始
您可以通过如下定义您的方法来实现
void Method<T>(T param)
where T: IFoo, IBar
{
}
void方法(T参数)
其中T:IFoo,IBar
{
}
希望这会有所帮助。对于方法返回后不会持久化的内容,可以使用受约束的泛型参数。不幸的是,它们有一个很大的局限性。一种方法,例如: void foo(T param) where T:IFoo,IBar {...} 如果对象支持方法族,请执行以下操作: void DoSomethingWithMe(IActUpon<T,U> proc); void DoSomethingWithMe(IActUpon<T,U,PT1> proc, ref PT1 p1); void DoSomethingWithMe(IActUpon<T,U,PT1,PT2> proc, ref PT1 p1, ref PT2 p2); 无效剂量(IActUpon proc); 无效剂量与时间(IActUpon proc,参考PT1 p1); 无效剂量与时间(IActUpon proc,参考PT1 p1,参考PT2 p2); 通过创建一个简单的类来实现
IActUpon
的适当变体,可以让对象调用任何需要约束到类型T和U的参数的所需例程
不幸的是,虽然这种方法几乎是通用的(最大的限制是必须为任何特定数量的泛型参数显式编码),但充其量也很尴尬。有了一些编译器支持,它可能不会太糟糕,但是对于一般用途来说,它可能太讨厌了。谢谢你的回答,我喜欢泛型方法的解决方法:-)可惜我没有泛型属性。我想当我需要时,我会使用一个通用的
getX()
/setX()
对。
interface IActUpon<T,U> {
void DoSomething<MT>(ref MT it) where MT:T,U;
}
interface IActUpon<T,U,PT1> {
void DoSomething<MT>(ref MT it, ref PT1 p1) where MT:T,U;
}
interface IActUpon<T,U,PT1,PT2> {
void DoSomething<MT>(ref MT it, ref PT1 p1, ref PT2 p2) where MT:T,U;
}
void DoSomethingWithMe(IActUpon<T,U> proc);
void DoSomethingWithMe(IActUpon<T,U,PT1> proc, ref PT1 p1);
void DoSomethingWithMe(IActUpon<T,U,PT1,PT2> proc, ref PT1 p1, ref PT2 p2);