定义实现+运算符的通用
可能重复:
.NETgenerics中重载运算符约束的解决方案
我有一个问题,我正在努力,目前它正在为int
工作,但我希望它适用于所有可以使用+
运算符添加的类。 有没有办法在通用中定义它? 例如,
public List Foo() where T : ISummable
有没有办法做到这一点?
编辑:
传入委托进行求和而不是使用+ =类型为Int的性能最好慢540%。 调查可能的其他解决方案
最终解决方案
谢谢大家的建议。 我最终找到了一个不太慢的解决方案,并在编译时强制执行检查。 当一位同事帮我解决这个问题时,我无法完全信任。 无论如何,这里是:
以函数的forms实现一个包含所有必需操作符的接口
public interface IFoo { //Adds A to B and returns a value of type OutputType OutputType Add(InputType a, InputType b); //Subtracts A from B and returns a value of type OutputType OutputType Subtract(InputType a, InputType b); }
创建要定义的类,但不使用Where子句,而是使用IFoo接口的依赖项注入实例。 OutputType通常是双倍的,因为操作的性质是数学的。
public class Bar { private readonly IFoo _operators; public Bar(IFoo operators) { _operators = operators; } }
现在,当您使用此类时,您可以像这样定义操作规则:
private class Foo : IFoo { public double Add(int a, int b) { return (double)(a+b); } public double Subtract(int a, int b) { return (double)(ab); } }
然后你会像这样使用它:
Foo inttoDoubleOperations = new Foo(); Bar myClass = new Bar(Foo);
这样所有操作都在编译时强制执行:)
请享用!
这是C#非常常见的新function:能够指定比我们已有的更通用的参数约束。 运营商是最常被问到的。 但是,C#目前不支持此function。
可能的解决方法:
-
将委托传递给任何需要添加的方法。 这是最类型安全的选项,但是如果你需要经常调用这样的方法,那当然很烦人。 例如:
public class Generic
{ public void DoSomething(T anItem, T anotherItem, Func add) { // instead of Blah(anItem + anotherItem); // have to write: Blah(add(anItem, anotherItem)); } } Generic genInt = ...; // and then instead of ... genInt.DoSomething(1, 2); // have to write: genInt.DoSomething(1, 2, (a, b) => a + b); -
声明自己的接口
IAddable
。 然后你可以将它用作generics类型参数约束,但显然你不能使用int
作为参数。 您必须使用自己的struct
,IAddable
包含一个int
并实现IAddable
:public interface IAddable
{ T Add(T other); } public struct Integer : IAddable { public int Value; public Integer(int value) { Value = value; } public Integer Add(Integer other) { return new Integer(Value + other.Value); } } // then instead of Generic blah = ...; // have to write: Generic blah = ...; -
dynamic
。 另一种可能的解决方法是使用dynamic
,但这是相当hacky并且完全不安全:它将允许您传入任何类型并调用任何方法或操作符,并且只在运行时崩溃,而不是在编译时崩溃。
在C#4.0中是新的关键字动态 ,允许您在运行时执行此操作。 在以前的版本中它可能但对我来说太阴暗和棘手。 但是你可以总是传递一个代理,它将在generics中执行添加。 否则它是不可能的,因为没有ISummable,IAdditive,一般来说,没有办法知道在编译时是什么是加法*。 如果您希望得到进一步的评论,我会在以后添加。 BR。
- 我的意思是,除了让你拥有IAdditive并用它们标记某些类型,但它不会用例如int。