Ter*_*lis 8 c# generics operators
可能重复:
.NET泛型中重载运算符约束的解决方案
我有一个问题我正在努力,目前它正在为ints 工作,但我希望它适用于所有可以使用+运算符添加的类.有没有办法在通用中定义它?例如,
public List<T> Foo<T>() where T : ISummable
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?
编辑:
传递代理进行求和而不是使用+ =类型的Int的性能最好慢540%.调查可能的其他解决方案
最终解决方案:
谢谢大家的建议.我最终找到了一个不太慢的解决方案,并在编译时强制执行检查.当一位同事帮我解决这个问题时,我无法完全信任.无论如何,这里是:
以函数的形式实现一个包含所有必需操作符的接口
public interface IFoo<InputType, OutputType>
{
//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);
}
Run Code Online (Sandbox Code Playgroud)
创建要定义的类,但不使用Where子句,而是使用IFoo接口的依赖注入实例.OutputType通常是双倍的,因为操作的性质是数学的.
public class Bar<T>
{
private readonly IFoo<T,double> _operators;
public Bar(IFoo<T, double> operators)
{
_operators = operators;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当您使用此类时,您可以像这样定义操作规则:
private class Foo : IFoo<int, double>
{
public double Add(int a, int b)
{
return (double)(a+b);
}
public double Subtract(int a, int b)
{
return (double)(a-b);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你会像这样使用它:
Foo inttoDoubleOperations = new Foo();
Bar myClass = new Bar(Foo);
Run Code Online (Sandbox Code Playgroud)
这样所有操作都在编译时强制执行:)
请享用!
这是C#非常常见的新功能:能够指定比我们已有的更通用的参数约束.运营商是最常被问到的.但是,C#目前不支持此功能.
可能的解决方法:
将委托传递给任何需要添加的方法.这是最类型安全的选项,但是如果你需要经常调用这样的方法,那当然很烦人.例如:
public class Generic<T> {
public void DoSomething(T anItem, T anotherItem, Func<T, T, T> add) {
// instead of
Blah(anItem + anotherItem);
// have to write:
Blah(add(anItem, anotherItem));
}
}
Generic<int> genInt = ...;
// and then instead of ...
genInt.DoSomething(1, 2);
// have to write:
genInt.DoSomething(1, 2, (a, b) => a + b);
Run Code Online (Sandbox Code Playgroud)声明自己的界面IAddable.然后您可以将它用作泛型类型参数约束,但显然您不能将其int用作参数.你必须使用struct你自己的一个只包含一个int和哪个实现IAddable:
public interface IAddable<T> {
T Add(T other);
}
public struct Integer : IAddable<Integer> {
public int Value;
public Integer(int value) { Value = value; }
public Integer Add(Integer other) { return new Integer(Value + other.Value); }
}
// then instead of
Generic<int> blah = ...;
// have to write:
Generic<Integer> blah = ...;
Run Code Online (Sandbox Code Playgroud)dynamic.另一个可能的解决方法是使用dynamic,但这是相当hacky和完全不安全:它将允许您传入任何类型并调用任何方法或操作符,并且只在运行时崩溃,而不是在编译时崩溃.