2015-02-04 2 views
2

에 구속되지 않은 제네릭 형식 매개 변수를 전달 나도 방법이 있습니다제한된 방법

public TValueType? DoStuffWithValueType<TValueType>(int x, int y) 
    where TValueType: struct {} 

public TRefType DoStuffWithRefType<TRefType>(int x, int y) 
    where TRefType: class {} 

내가 어떻게 그들을 포장 할 수있는 새로운 세 번째 방법을?

DoStuffWithValueType를 호출 할 때 내가 T이 구조체 사실에 컴파일러를 설득 할 수 없기 때문에 컴파일되지 다음

public T DoStuff<T>(int x, int y) { 

    if(typeof(T).IsValueType) 
    { 
     return DoStuffWithValueType<T>(x, y); 
    } 

    return DoStuffWithRefType<T>(x, y); 
} 

이미 DoStuff 과부하했지만,이 시도가 제네릭 제약 조건에 포함되지 않기 때문에 실패 메소드 서명의
나는 또한 제약 조건을 없애려고했지만 그럴 수 없었다.

아이디어가 있으십니까? 고맙습니다!

+1

사전 경고 : 유형이 값 유형이라는 사실이 반드시 그것이 struct 제약 조건에 대한 유효한 제네릭 유형 인수라는 것을 의미하지는 않습니다. Nullable 값 유형은'class' 또는'struct' 제약 조건과 함께 사용할 수 없습니다. – hvd

답변

2

기본적으로, 당신은 반사와 관련된 메서드를 호출해야 할 것입니다. 그것은 추한 것입니다. 물론

당신은 당신으로부터 반사를 숨 깁니다 동적 타이핑,이 작업을 수행 할 수 있습니다

public T DoStuff<T>(int x, int y) { 
    dynamic d = this; 
    if(typeof(T).IsValueType) 
    { 
     return d.DoStuffWithValueType<T>(x, y); 
    }  
    return d.DoStuffWithRefType<T>(x, y); 
} 

당신은 그 반사와 함께 수동으로하는 것보다 청소기의 생각 - 또는 :)하지 않을 수 있습니다

필자는 컴파일러가 일반적으로 그렇게하지 않는 형식의 인수를 "신뢰"하도록하는 방법이 없습니다.

+0

감사합니다! 자신과 같은 유명인이 제 질문 중 하나에 대답 할 것이라고 생각하지 않았습니다.) – keydon

1

Jon Skeet이 사용하는 dynamic을 제외하고 필자가 생각할 수있는 가장 깨끗한 방법은 필요한 리플렉션을 최소화하고 컴파일러에서 가능한 한 많이 확인하여 도우미 클래스를 통해 메서드를 호출하는 것입니다.

abstract class DoStuffHelper<T> { 
    public abstract T DoStuff(int x, int y); 
} 

class DoStuffWithValueTypeHelper<T> : DoStuffHelper<T> where T : struct { 
    public override T DoStuff(int x, int y) { 
     return DoStuffWithValueType<T>(x, y); 
    } 
} 

class DoStuffWithRefTypeHelper<T> : DoStuffHelper<T> where T : class { 
    public override T DoStuff(int x, int y) { 
     return DoStuffWithRefType<T>(x, y); 
    } 
} 

public T DoStuff<T>(int x, int y) { 
    DoStuffHelper<T> helper; 
    Type helperType; 

    if(typeof(T).IsValueType) 
     helperType = typeof(DoStuffWithValueTypeHelper<>); 
    else 
     helperType = typeof(DoStuffWithRefTypeHelper<>); 

    helperType = helperType.MakeGenericType(typeof(T)); 
    helper = (DoStuffHelper<T>)Activator.CreateInstance(helperType); 

    return helper.DoStuff(x, y); 
} 

는 상황에 맞는 적절한 경우에, 당신은 그들에게 모든 시간을 다시 만드는 것을 방지하기 위해 Dictionary<Type, object>의 헬퍼 클래스를 캐시 할 수 있습니다.

관련 문제