2013-03-12 9 views
5

Wystąpił problem z przeciążaniem metod, które mają różne ograniczenia, które wydają się wyłączne. To jest mój przykład:Członek z tym samym sygnaturą, który już został zdefiniowany z różnymi typami ograniczeń.

public class A 
{ 
    public void Do<T>() where T : class 
    { 

    } 

    public void Do<T>() where T : struct 
    { 

    } 
} 

I to nie kompiluje się z powodu następującego błędu „członek z tym samym podpisem już zdefiniowany”. Czy możliwe jest spełnienie obu warunków jednocześnie, czy to tylko ograniczenie kompilatora C#?

Odpowiedz

8

To nie jest ograniczenie kompilatora - to ograniczenie języku (i całkiem możliwe, że CLR, jak również, że nie jestem pewien).

Zasadniczo są to ścieranie się przeciążenia - to tak, jakby próbować przeciążać przez typ zwrotu. To nie jest obsługiwane.

To jest można zadeklarować metody takie, że te rozmowy wszystko skompilować do wywołania różnych metod:

a.Do<int>(); 
a.Do<string>(); 
a.Do<int?>(); 

... ale to zawsze wiąże parametry opcjonalne i/lub tablic parametrów, a to horrible.

Należy również zauważyć, że chociaż nie można przeciążać przez ogólnych ograniczeń, ty może przeciążeniem rodzajową „liczbę operandów” (liczba parametrów typ):

public void Foo() {} 
public void Foo<T>() {} 
public void Foo<T1, T2>() {} 
+0

Przynajmniej mam nadzieję, że to było prawdą, że te dwa ograniczenia są wyłączną i to tylko ograniczenie , dobrze? :) –

+0

@IlyaChernomordik: To ograniczenie, ale całkiem rozsądne jedno IMO. –

+0

Ale co jest złego w zezwalaniu na to? Po prostu muszę wykonać różne czynności w zależności od tego, czy chodzi o klasę (mogę sprawdzić, czy jest to wartość null), czy o ile jest długa (wtedy wiem, że ta wartość istnieje). Tak więc wyjście powinno polegać na nadawaniu różnych nazw metodom, które wydaje. Zdecydowanie nie chcę używać tej koszmarnej drogi :) –

2

Nie można przeciążyć metodę, dzięki varing ogólny parametr zawiera. Dla prawidłowego przeciążenia metody musisz mieć różne parametry wejściowe do metody.

1

Obie metody powinny mieć następującą nazwę gdy kompilowany:

A.Do``1 

Jako liczby parametrów ogólnych idzie do nazwy metody lub klasy.

Nie wiesz, co twoja sytuacja jest, ale może trzeba skorzystać z refleksji wywołać te metody:

public class A 
{ 
    public void Do<T>() 
    { 
     if(typeof(T).IsValueType){ 
      // nasty reflection to call DoValueType 
     } 
     else { 
      // nasty reflection to call DoReferenceType 
     } 
    } 
    private void DoReferenceType<T>() where T : class { 

    } 
    private void DoValueType<T>() where T : struct { 

    } 
} 
Powiązane problemy