2009-04-15 9 views
16

W tej chwili mam to z Guid s.Nie można niejawnie przekształcić typu "X" na "ciąg" - kiedy i jak decyduje, że "nie może"?

Z pewnością pamiętam, że w całym kodzie w niektórych miejscach ta niejawna konwersja działa, w innych nie. Do tej pory nie widzę wzoru.

Jak kompilator decyduje, kiedy nie może? Chodzi mi o to, że istnieje metoda typu Guid.ToString(), czy nie jest ona wywoływana, ilekroć ta transformacja jest potrzebna?

Czy ktoś może mi powiedzieć, w jakich okolicznościach ta transformacja jest wykonywana automatycznie i kiedy muszę wyraźnie zadzwonić pod numer myInstance.ToString()?

+0

(dodano komentarz do pytania) –

+0

Próba i błąd. Trial i błąd. – Will

Odpowiedz

32

W skrócie, gdy istnieje bezpośrednia lub pośrednia operator konwersji zdefiniowane:

class WithImplicit { 
    public static implicit operator string(WithImplicit x) { 
     return x.ToString();} 
} 
class WithExplicit { 
    public static explicit operator string(WithExplicit x) { 
     return x.ToString(); } 
} 
class WithNone { } 

class Program { 
    static void Main() { 
     var imp = new WithImplicit(); 
     var exp = new WithExplicit(); 
     var none = new WithNone(); 
     string s1 = imp; 
     string s2 = (string)exp; 
     string s3 = none.ToString(); 
    } 
} 
+2

Po prostu sprawdziłem to dla siebie. Nie mogę uwierzyć, że tęskniłem za tym wszystkim przez te wszystkie lata z C#. Chyba nigdy tego nie potrzebowałem ... Dziękuję, że nauczyłeś mnie dzisiaj czegoś nowego. – User

+0

Gdzie muszę zdefiniować ten operator? W klasie Type chyba? Nie mogę dodać statycznych rozszerzeń do klas WithImplicit i WithExplicit. – User

+0

Nie; nie ma czegoś takiego jak operator rozszerzenia. –

4

Jedynym miejscem, gdzie można skutecznie nie trzeba zadzwonić toString(), gdy sam jest łączenie ciągów.

Guid g; 
int i; 
string s = "Hello "+g+' '+i; 

Następnie istnieją pewne sytuacje, w których połączenie zostanie dokonane przez .NET Framework, takie jak w String.Format().

Poza tym kompilator konwertuje typ tylko wtedy, gdy jest znany jako zgodny (np. Klasa bazowa lub implementuje interfejs lub przez wyraźnie zakodowany operator konwersji). Kiedy używasz rzutowania, a kompilator wie, że typy nie mogą być kompatybilne (na przykład nie w tej samej linii dziedziczenia, a nie w interfejsach), będzie również mówić, że nie może go przekonwertować. To samo dotyczy ogólnych parametrów typu.

+0

Nieprawidłowe; kompilator szanuje również operatory konwersji. Zobacz mój post na przykłady konwersji niejawnych i jawnych, które * nie * wymagają, aby wywołujący używał ToString() lub łączenia ciągów. –

+0

Masz rację co do operatorów konwersji, ale zazwyczaj ich omijam, więc nie wspomniałem o nich tutaj.Zmienię moją odpowiedź. – Lucero

4

Nie, nie ma żadnej niejawnej konwersji z GUID na String, więc to nie działa nigdzie w ogóle w kodzie.

Działa tylko w przypadku wyraźnej konwersji, ale konwersja może nie być bardzo widoczna. Na przykład podczas łączenia ciągów:

string id = "--" + guidValue + " : " + num; 

Może to wyglądać niejawna konwersja z GUID do String, ale tak nie jest. Kod, który jest generowany w rzeczywistości wygląda to tak:

string id = String.Concat(new object[] { "--", guidValue, " : ", num }); 

Wszystkie argumenty są odlewane z typem Object i umieszczone w tablicy. Metoda String.Concat następnie wywołuje metodę ToString dla każdego elementu w tablicy, aby uzyskać dla nich reprezentację ciągów znaków.

Powiązane problemy