C#泛型运营商(C# Generic Operators)

2019-10-17 20:02发布

我想实现一个通用的操作,如下所示:

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。 我希望有一个通用的运营商+解决这个问题,但我只是得到一个语法错误的上述(在<)使我相信,这样的代码是不合法的。

有没有一种方法,使一个通用的运营商?

Answer 1:

不,你不能声明在C#泛型运营商。

运营商和继承真的不拌匀。

如果你想美孚+富返回一个Foo和Bar +酒吧返回一个吧,你将需要在每类中定义一个运营商。 但是,因为运营商是静态的,你不会得到多态性,因为它操作调用会在编译时决定的好处:

Foo x = new Bar();
Foo y = new Bar();
var z = x + y; // calls Foo.operator+;


Answer 2:

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);       
}


Answer 3:

你可以只在一个通用类Foo定义操作。

您还可以创建真正通用的运营商,但C#编译器不会使用它们。

[System.Runtime.CompilerServices.SpecialName]
public static T op_Addition<T>(T a, T b) { ... }


Answer 4:

你不能在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;
}

您可能也有兴趣在这个简短的总结文章 ,我碰到。



Answer 5:

在寻找同样的事情,谷歌把我带到这里....我是不是太高兴接受的答案,并寻找解决方法。

我成功地实现这个使用泛型。 这里是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.


文章来源: C# Generic Operators