Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET泛型中重载运算符约束的解决方案_C#_Generics_Operator Overloading_Constraints - Fatal编程技术网

C# .NET泛型中重载运算符约束的解决方案

C# .NET泛型中重载运算符约束的解决方案,c#,generics,operator-overloading,constraints,C#,Generics,Operator Overloading,Constraints,如果我想要一个泛型方法,它只接受重载了运算符的类型,例如减法运算符,该怎么办。我尝试使用接口作为约束,但接口不能有运算符重载 实现这一目标的最佳方法是什么?没有立即的答案;运算符是静态的,不能在约束中表示,并且现有的primative没有实现任何特定的接口(与可用于模拟大于/小于的IComparable[]相反) 但是,;如果您只是想让它工作,那么在.NET3.5中有一些选项 我已经建立了一个库,允许高效、简单地访问具有泛型的运算符,例如: T result = Operator.Add(fir

如果我想要一个泛型方法,它只接受重载了运算符的类型,例如减法运算符,该怎么办。我尝试使用接口作为约束,但接口不能有运算符重载


实现这一目标的最佳方法是什么?

没有立即的答案;运算符是静态的,不能在约束中表示,并且现有的primative没有实现任何特定的接口(与可用于模拟大于/小于的IComparable[]相反)

但是,;如果您只是想让它工作,那么在.NET3.5中有一些选项

我已经建立了一个库,允许高效、简单地访问具有泛型的运算符,例如:

T result = Operator.Add(first, second); // implicit <T>; here
我曾经有过一个.NET2.0版本,但测试较少。另一个选项是创建一个接口,例如

interface ICalc<T>
{
    T Add(T,T)() 
    T Subtract(T,T)()
} 
接口ICalc
{
T加(T,T)()
T减去(T,T)()
} 

等等,但是你需要传递一个
ICalc通过所有的方法,这变得很混乱。

我发现IL实际上可以很好地处理这个问题。前

ldarg.0
ldarg.1
add
ret
在泛型方法中编译,只要指定了基元类型,代码就可以正常运行。可以将其扩展为在非基元类型上调用运算符函数


请参阅。

有一段代码是从互联网上偷来的,我经常用它来做这件事。它使用
IL
基本算术运算符查找或构建。这一切都是在
操作
泛型类中完成的,您所要做的就是将所需的操作分配给一个委托。像
add=Operation.add

它是这样使用的:

public struct MyPoint
{
    public readonly double x, y;
    public MyPoint(double x, double y) { this.x=x; this.y=y; }
    // User types must have defined operators
    public static MyPoint operator+(MyPoint a, MyPoint b)
    {
        return new MyPoint(a.x+b.x, a.y+b.y);
    }
}
class Program
{
    // Sample generic method using Operation<T>
    public static T DoubleIt<T>(T a)
    {
        Func<T, T, T> add=Operation<T>.Add;
        return add(a, a);
    }

    // Example of using generic math
    static void Main(string[] args)
    {
        var x=DoubleIt(1);              //add integers, x=2
        var y=DoubleIt(Math.PI);        //add doubles, y=6.2831853071795862
        MyPoint P=new MyPoint(x, y);
        var Q=DoubleIt(P);              //add user types, Q=(4.0,12.566370614359172)

        var s=DoubleIt("ABC");          //concatenate strings, s="ABCABC"
    }
}

你有没有一个例子说明你在哪里尝试使用这个?我想不出任何有用的地方?正如您所发现的,在接口上定义静态方法是不可能的,因此您不能将其用作泛型方法的约束。这里有一个有点复杂的解决方法:如果您使用的是.NET3.5,也可以通过LINQ表达式树来实现,如下所示:通用的“求和”方法就是一个简单的例子。T和(IEnumerable序列);//其中T有“+”运算符请注意,在Roger的博客中,我们讨论/对比了这两种实现(它们非常相似),得出的结论是MiscUtil代码(前面链接过)更加发达。但是他们使用相同的基本方法。我喜欢在.NET4.0中使用动态的功能,它确实使事情变得更容易。然而,值得指出的是,使用它会影响性能,因为它必须在运行时做更多的工作。我很想知道它有多大的影响,我认为它需要一些基准测试;从这里尝试代码:我尝试了您的库(针对.NET3.5),我有一个问题:为什么下面的行不起作用:MiscUtil.Operator.Add(“a”,“B”);。在我的理解中,它应该返回“AB”。@Malki-好吧,我们可以加上它,但这不是真正的算术运算。严格地说,它并不是一个真正定义的操作符——它是编译器(而不是类型本身),为字符串提供了
+
的含义……如果它要转换为动态的,使用泛型有什么意义吗?为什么不让参数和返回代码也成为动态的呢?以这种方式混合泛型和动态有什么好处吗?哦,我只看到了
dynamic
关键字解决方案。
public struct MyPoint
{
    public readonly double x, y;
    public MyPoint(double x, double y) { this.x=x; this.y=y; }
    // User types must have defined operators
    public static MyPoint operator+(MyPoint a, MyPoint b)
    {
        return new MyPoint(a.x+b.x, a.y+b.y);
    }
}
class Program
{
    // Sample generic method using Operation<T>
    public static T DoubleIt<T>(T a)
    {
        Func<T, T, T> add=Operation<T>.Add;
        return add(a, a);
    }

    // Example of using generic math
    static void Main(string[] args)
    {
        var x=DoubleIt(1);              //add integers, x=2
        var y=DoubleIt(Math.PI);        //add doubles, y=6.2831853071795862
        MyPoint P=new MyPoint(x, y);
        var Q=DoubleIt(P);              //add user types, Q=(4.0,12.566370614359172)

        var s=DoubleIt("ABC");          //concatenate strings, s="ABCABC"
    }
}
/* Copyright (C) 2007  The Trustees of Indiana University
 *
 * Use, modification and distribution is subject to the Boost Software
 * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *  
 * Authors: Douglas Gregor
 *          Andrew Lumsdaine
 *          
 * Url:     http://www.osl.iu.edu/research/mpi.net/svn/
 *
 * This file provides the "Operations" class, which contains common
 * reduction operations such as addition and multiplication for any
 * type.
 *
 * This code was heavily influenced by Keith Farmer's
 *   Operator Overloading with Generics
 * at http://www.codeproject.com/csharp/genericoperators.asp
 *
 * All MPI related code removed by ja72. 
 */