我想实现一个通用的操作,如下所示:
class Foo
{
public static T operator +<T>(T a, T b)
{
// Do something with a and b that makes sense for operator + here
}
}
真的是我想要做的是妥善处理继承。 随着标准的运营商+ Foo中,其中T是不是“富”,如果有人从美孚派生(比如酒吧继承美孚),然后一个酒吧+酒吧操作仍然会返回一个Foo。 我希望有一个通用的运营商+解决这个问题,但我只是得到一个语法错误的上述(在<)使我相信,这样的代码是不合法的。
有没有一种方法,使一个通用的运营商?
不,你不能声明在C#泛型运营商。
运营商和继承真的不拌匀。
如果你想美孚+富返回一个Foo和Bar +酒吧返回一个吧,你将需要在每类中定义一个运营商。 但是,因为运营商是静态的,你不会得到多态性,因为它操作调用会在编译时决定的好处:
Foo x = new Bar();
Foo y = new Bar();
var z = x + y; // calls Foo.operator+;
https://jonskeet.uk/csharp/miscutil/usage/genericoperators.html
static T Add<T>(T a, T b) {
//TODO: re-use delegate!
// declare the parameters
ParameterExpression paramA = Expression.Parameter(typeof(T), "a"),
paramB = Expression.Parameter(typeof(T), "b");
// add the parameters together
BinaryExpression body = Expression.Add(paramA, paramB);
// compile it
Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
// call it
return add(a,b);
}
你可以只在一个通用类Foo定义操作。
您还可以创建真正通用的运营商,但C#编译器不会使用它们。
[System.Runtime.CompilerServices.SpecialName]
public static T op_Addition<T>(T a, T b) { ... }
你不能在C#中声明的通用运营商 - 我不知道的理由,但认为这是一个有用VS努力的事情实施团队(我相信有可能是在这里的乔恩斯基特后讨论它,或者在自己的博客时,他讨论的事情,他想在C#中看到)。
事实上,你甚至不能使用运营商在C#泛型。
这是因为仿制药必须是适用于可提供所有可能的类型。 这就是为什么你必须范围泛型类型的类时要使用==
如下:
void IsEqual<T>(T x, T y) where T : class
{
return x == y;
}
不幸的是,你不能这样做:
void Add<T>(T x, T y) where T : operator +
{
return x + y;
}
您可能也有兴趣在这个简短的总结文章 ,我碰到。
在寻找同样的事情,谷歌把我带到这里....我是不是太高兴接受的答案,并寻找解决方法。
我成功地实现这个使用泛型。 这里是Foo和酒吧类:
class Foo
{
private int value;
public Foo(int x)
{
value = x;
}
public virtual int getVal()
{
return value;
}
}
class Bar : Foo
{
private int derivedValue;
public Bar(int x):base(x)
{
derivedValue = x;
}
public override int getVal()
{
return derivedValue;
}
}
然后将含有运营商,但仅限于Foo类型的和衍生自富一个通用类:
class GenericOp<T> where T : Foo
{
private T value;
public GenericOp(T x)
{
value = x;
}
public static Foo operator +(GenericOp<T> a, GenericOp<T> b)
{
return new Foo(a.value.getVal() + b.value.getVal());
}
}
展示你总是得到一个富以及阻止你混合类型的一些使用的代码:
Foo f1 = new Foo(1);
Foo f2 = new Foo(2);
Bar b1 = new Bar(10);
Bar b2 = new Bar(20);
GenericOp<Foo> left = new GenericOp<Foo>(f1);
GenericOp<Foo> right = new GenericOp<Foo>(f2);
Foo res = left + right;
GenericOp<Bar> left1 = new GenericOp<Bar>(b1);
GenericOp<Bar> right1 = new GenericOp<Bar>(b2);
Foo res1 = left1 + right1;
GenericOp<Foo> left2 = new GenericOp<Foo>(f1);
GenericOp<Bar> right2 = new GenericOp<Bar>(b1);
//Foo res2 = left2 + right2; //this fails and rightfully so.