2008-09-29 4 views
30

연산자를 오버로드 한 형식 (예 : 빼기 연산자) 만 허용하는 일반 메서드를 사용하려면 어떻게해야합니까? 제약 조건으로 인터페이스를 사용했지만 인터페이스에 연산자 오버로딩을 사용할 수 없습니다..NET 제네릭에서 오버로드 된 연산자 제약 조건에 대한 솔루션

이것을 달성하는 가장 좋은 방법은 무엇입니까?

+1

당신의 예를 가지고 수행을 시도하는 경우 이것을 사용 하시겠습니까? 나는 어디에서나 유용하다고 생각할 수 없다. –

+0

일반적인 "Sum"메서드는 간단한 예제입니다. T Sum (IEnumerable 시퀀스); // T가 '+'연산자 인 경우 – blackwing

+0

[+ 연산자를 구현하는 제네릭 정의] 가능한 복제본 (http://stackoverflow.com/questions/3598341/define-a-generic-that-implements-theoperator) – Timwi

답변

37

즉각적인 대답은 없습니다. 연산자는 정적이며 제약 조건으로 표현할 수 없습니다. 기존의 프리미티브는 특정 인터페이스를 구현하지 않습니다 (IComparable [<T>]와 비교하여보다 크거나 같음을 에뮬레이션하는 데 사용할 수 있음).

그러나; 당신은 그냥 작업 할 경우, 다음 .NET 3.5에 내가 함께 넣어 가지고

... 몇 가지 옵션이 있습니다 제네릭과 운영에 효율적이고 간단하게 액세스 할 수 있습니다 라이브러리 here - 같은 :

T result = Operator.Add(first, second); // implicit <T>; here 

가 이것은 C# 4.0, 또한 MiscUtil

의 일부로서 다운로드 될 수 있으며, 이는 dynamic 통해 가능해진다 :

static T Add<T>(T x, T y) { 
    dynamic dx = x, dy = y; 
    return dx + dy; 
} 

또한 (한 지점에서) .NET 2.0 버전을 가지고 있었지만 테스트가 덜 까다 롭습니다. 다른 옵션은

interface ICalc<T> 
{ 
    T Add(T,T)() 
    T Subtract(T,T)() 
} 

등과 같은 인터페이스를 만드는 것입니다,하지만 당신은 지저분 모든 방법을 통해 ICalc<T>;을 통과해야합니다.

+0

.NET 4.0에서 동적 기능을 사용하기를 좋아합니다. 그러나 런타임시 더 많은 작업을해야하기 때문에 성능에 영향을 미칠 수 있다는 점을 지적하는 것이 중요합니다. 나는 그것이 얼마나 많은 영향을 미치는지 알기를 원할 것이다. 나는 생각하기에 벤치마킹이 필요하다. –

+0

벤치 마크 완료. 여기에서 코드를 시도하십시오. http://social.msdn.microsoft.com/Forums/en-US/vs2010ctpvbcs/thread/287db1b9-c135-40bc-a1c5-a8a51efbfc65 –

+0

나는 (.NET 3.5 용) 라이브러리를 사용해 보았습니다. 그리고 나는 다음의 라인이 작동하지 않는 이유가 무엇인지 질문한다 : MiscUtil.Operator.Add ("A", "B"); 제 생각에 "AB"가 반환됩니다. – Malki

5

IL이 실제로 이것을 상당히 잘 처리 할 수 ​​있다는 것을 알았습니다. 전의.

ldarg.0 
ldarg.1 
add 
ret 

일반 메서드로 컴파일 된 코드는 기본 형식이 지정되어 있으면 정상적으로 실행됩니다. 비 프리미티브 유형의 연산자 함수를 호출하기 위해이를 확장 할 수 있습니다.

here을 참조하십시오.

-1

내가 많이 사용하는 인터네트에서 도난당한 코드 조각이 있습니다. IL 기본 산술 연산자를 사용하여 찾습니다. 그것은 모두 Operation<T> 일반 클래스 내에서 이루어 지므로 필요한 작업을 대리인에게 할당하면됩니다. add = Operation<double>.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" 
    } 
} 

Operation<T> 소스 코드 사의 씨 : 아래의 속성과 http://pastebin.com/nuqdeY8z

: 당신이

/* 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. 
*/ 
+0

위로 가기 답변은 이미이 방법을 사용하여 설명합니다. – Servy

+0

아, 동적 키워드 솔루션 만 보았습니다. – ja72

관련 문제