2011-10-21 4 views
1

가 인터페이스를 가지고 할 수있는 방법이 있나요 구체적인 클래스를 만들려면 다음일반 클래스는 말한다, 자동으로

/// <summary> 
/// Interface containing operators which operate on T 
/// </summary> 
public interface IScalarOperators<T> 
{ 
    // Adds two T objects 
    IOperateScalar<T> OperatorAdd { get; } 
    // Subtracts two T objects 
    IOperateScalar<T> OperatorSubtract { get; } 
    // Multiplies two T objects 
    IOperateScalar<T> OperatorMultiply { get; } 
} 

// Class containing all the Scalar operators for a given T 
class ScalarOperators<T> : IScalarOperators<T> 
{ 
    public IOperateScalar<T> OperatorAdd { get; private set; } 
    public IOperateScalar<T> OperatorSubtract { get; private set; } 
    public IOperateScalar<T> OperatorMultiply { get; private set; } 
    private ScalarOperators(IOperateScalar<T> add, IOperateScalar<T> subtract, IOperateScalar<T> multiply) 
    { 
     this.OperatorAdd = add; 
     this.OperatorSubtract = subtract; 
     this.OperatorMultiply = multiply; 
    } 

    public static ScalarOperators<bool> CreateBool() 
    { 
     return new ScalarOperators<bool>(new AddBool(), new SubtractBool(), new MultiplyBool()); 
    } 

    public static ScalarOperators<int> CreateInt() 
    { 
     return new ScalarOperators<int>(new AddInt(), new SubtractInt(), new MultiplyInt()); 
    } 

    // METHOD I WANT TO ADD 
    public static ScalarOperators<T> Create() 
    { 
     // if T == bool 
     // return CreateBool() 
     // if T == int 
     // return CreateInt() 
     // else (no definition available for T) 
     // return null 
    } 

    // I tried something like below, but it didn't work... 
    public static ScalarOperators<T> Create<T>() where T: bool 
    { return CreateBool(); } 

    public static ScalarOperators<T> Create<T>() where T : int 
    { return CreateInt(); } 

    public static ScalarOperators<T> Create<T>() 
    { return null; } 
} 

공지 사항, 나는 사업자의 정확한 세트를 작성하는 일반적인 작성 방법을하고 싶습니다,하지만 난 그것을하는 방법을 모르겠다.

나는이 방법에서 매개 변수를 제거하는 데 사용하고 싶습니다 :

public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other, IScalarOperators<T> operators) 
    { 
     JoinCells<T> joiner = new JoinCells<T>(); 
     return joiner.Join(matrix, other, null, operators.OperatorAdd); 
    } 

은 어떤 도움

public static IMatrix<T> Add<T>(this IMatrix<T> matrix, IMatrix<T> other) 
    { 
     JoinCells<T> joiner = new JoinCells<T>(); 
     return joiner.Join(matrix, other, null, ScalarOperators<T>.Create().OperatorAdd); 
    } 

감사가된다! 주로 scalarOperator 객체를 확장 메서드에 전달하지 않으려는 경우 정의 된 T에 대해 ScalarOperators가 변경되지 않으므로 '기본'값을 갖는 것을 선호합니다. 당신 정말 만약 내가 대신 정적 클래스의 IScalarOperators의 공장을 (만드는 것이 좋습니다

public static ScalarOperators<T> Create() 
{ 
    Type type = typeof(T); 
    if(type == typeof(bool)) 
     return CreateBool() 
    if(type == typeof(int)) 
     return CreateInt() 
    else 
     return null 
} 
+0

일반 계산을 허용하도록 라이브러리를 만드는 것처럼 보입니까? [이 라이브러리] (http : //www.codeproject.com/KB/cs/genericnumerics.aspx). 최근에는 표현식 트리가 다른 멋진 솔루션을 제공합니다. [Marc Gravell 's MiscUtils] (http://www.yoda.arachsys.com/csharp/miscutil/usage/genericoperators.html) 구현을 확인하십시오. –

답변

2

은 다음과 같이 될 수 방법을 만들고, T.

의 유형

를 얻을 수있다 정적 필드가 있어야 정적 필드에 액세스 할 수 있습니다). 당신은 응용 프로그램 시작시를 등록하고이 예제 metod으로 그들을 얻을 수 있습니다 :

public IScalarOperators<T> Create<T>() 
{ 
    // check if exists in dictionary 
    return (ScalarOperators<T>)dict[typeof(T)]; 
} 

DICT 유형 사전이 될 것입니다. 새로운 구현 클래스를 생성하고 팩토리에 등록하면 응용 프로그램이 커지는 동안 새 IScalarOperators를 추가 할 수 있다는 점이 단점입니다. 또한 당신은 더 잘 분리 된 관심사와 (제 의견으로는)보다 깨끗한 코드를 갖게 될 것입니다.

3

을 : 당신이해야 할 일은

1

내가 여기서 생각해야 할 몇 가지 일이 여기에 있습니다. 사용자 지정 연산자를 자신이 조작하는 유형에서 분리하려고 시도하고 있는데, 이것은 혼란 스럽습니다. 그리고 당신은 generics에 대한 매우 광범위한 개념을 취하여이를 전문화하려고합니다.

처음에는 항상 동일한 유형의 연산자를 사용합니다. 적어도 int 형식에서는 bool 연산자를 사용하지 않을 것입니다. 별도의 수업을 받음으로써 복잡한 일을 할 이유가 없습니다. 후자의 경우 제네릭 클래스와 제네릭 메서드는 주어진 T에서 동일하게 작동합니다. 허용되는 경우 static 팩토리 메서드에서 typeof(T)을 가져 와서 여러 특정 사례에 대해 비교할 수 있습니다. 이와 같이 지나치게 복잡한 일반 피연산자 구조로 인해 처리하려는 모든 새 T에 대해이를 변경하십시오.

피연산자에 대한 일반 인터페이스를 만든 다음 해당 유형의 래퍼를 대신 구현하는 것이 좋습니다. 예를 들어, int는 다음과 같이 감쌀 수 있습니다.

public interface IScalarOperators<T> 
{ 
    IScalarOperators<T> Add (IScalarOperators<T> rightSide); 
    IScalarOperators<T> Subtract (IScalarOperators<T> rightSide); 
    IScalarOperators<T> Multiply (IScalarOperators<T> rightSide); 
    T Unwrap(); 
} 

public interface IMatrix<T> where T : IScalarOperators<T> { /* whatever */ } 

public class CustomInt : IScalarOperators<CustomInt> 
{ 
    private readonly int number; 
    public CustomInt(int number) { this.number = number; } 
    public CustomInt Unwrap() { return this; } 
    public IScalarOperators<CustomInt> Add(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number + rightSide.Unwrap().number); } 
    public IScalarOperators<CustomInt> Subtract(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number - rightSide.Unwrap().number); } 
    public IScalarOperators<CustomInt> Multiply(IScalarOperators<CustomInt> rightSide) { return new CustomInt(number * rightSide.Unwrap().number); } 
} 

그 시점에서, 당신은 IScalarOperators<T> 인터페이스를 통해 IMatrix<CustomInt>에서 작동하고 원하는 노출 된 작업을 수행 할 수 있습니다. 예를 들어, array이라는 접근자를 가지고 있다고 가정하면 IScalarOperators<T> result = matrix.array[0, 0].Add(matrix.array[0, 1]);이라고 말하면서 함께이 두 표현을 다시 표시 할 수 있습니다. 그런 다음 추가 작업을 수행 할 수 있습니다.