2016-02-19 13 views
15

Ho definito conversione di stringhe implicita da/a un certo tipo in C# (codice fittizio):Perché l'operatore "as" non utilizza un operatore di conversione implicito in C#?

public class MyType 
{ 
    public string Value { get; set; } 

    public static implicit operator MyType(string fromString) 
    { 
     return new MyType { Value = fromString }; 
    } 

    public static implicit operator string(MyType myType) 
    { 
     return myType.Value; 
    } 
} 

qualche parte nel codice libreria esterna, un'istanza di MyType viene passata ad un metodo, come parametro object. Parte di questo metodo assomiglia a qualcosa del genere:

private void Foo(object value) 
{ 
    // ... code omitted 
    var bar = value as string // note that value is an instance of MyType at runtime 
    if(bar != null) // false, cast fails 
    { 
     // ... code omitted 
    } 
} 

Perché il cast non utilizza il convertitore implicito? Pensavo che il punto fondamentale di questi fosse rendere possibile il casting e l'uso trasparente?

Questo funziona se MyType ha un convertitore explicit? Se è così, (come) posso avere entrambi?

A proposito, il cast funziona sicuramente se il tipo è noto al in fase di compilazione. È perché gli operatori sono static? C'è qualcosa come operatori di conversione non statici?

P.S. In realtà sono più interessati alle differenze tra il comportamento in fase di compilazione e di comportamento di runtime, quindi ho un follow-up domanda: Why are implicit type conversion operators not dynamically usable at runtime in C#?

+3

Per inciso, non ho mai sentito l'operatore 'as' indicato come" soft cast "prima. –

+0

@JonSkeet che mi sorprende davvero, forse non è un termine ufficiale, ma l'ho sicuramente visto molte volte. – MarioDS

+0

Una ricerca per "soft cast" e C# mi dà 636 risultati, che è un * minuscolo * numero nella mia vista. Lo eviterei sicuramente in futuro - è certamente * non * parte della terminologia specifica C#. –

risposta

19

Perché il cast morbido, non utilizzare il convertitore implicita?

Bene, questo è il modo in cui viene specificata la lingua, in pratica. Dalla C# 5 sezione specifica 7.10.11:

Se il tipo di fase di compilazione E non è dinamica, l'operazione E come T produce lo stesso risultato

E is T ? (T)(E) : (T)null 

tranne che E è solo valutato una volta.

[...]

noti che alcune conversioni, come le conversioni definite dall'utente, non sono possibili con l'operatore as e dovrebbe invece essere eseguite utilizzando espressioni del cast.

+0

Questo è abbastanza chiaro, ma dovresti sapere di eventuali soluzioni alternative? E se volessi davvero avere un tipo che si comporti quasi completamente come una stringa (o un int, o qualcos'altro per quella materia)? – MarioDS

+2

@MDeSchaepmeester: vorrei semplicemente rinunciare a questo come obiettivo, ad essere onesti. Ci sono sempre dei problemi quando si cerca di far sembrare un tipo in modo trasparente come un altro. Vorrei tornare indietro e guardare invece altri progetti. –

+0

Abbastanza onesto, ma se non fosse stato per questa limitazione, tutto avrebbe funzionato bene però. Grazie comunque, se non sai una soluzione alternativa, sono certo che nessun altro lo fa :) – MarioDS

9

Il # lingua specifica C menzioni esplicitamente nella documentazione per as:

Si noti che alcune conversioni, come le conversioni definite dall'utente, non sono possibile con la qualità di operatore e dovrebbero invece essere eseguite utilizzando espressioni espresse.

Quindi devi lanciarlo.

7

as parola chiave non considera gli operatori definiti dall'utente. È necessario invece utilizzare un operatore di trasmissione. operatori correlati article from eric lippert

Nel tuo caso sia esplicite che implicite non possono fare a voi come si sta cercando di lanciare object-string non dal MyType a string.Per gli operatori di conversione definiti dall'utente affinché funzionino, compila il tipo di orario dell'istanza in modo che sia di tipo MyType anziché object. Perché non esiste alcuna conversione da object a string ma da MyType a string.

+0

L'uso di 'dynamic' farebbe funzionare il cast, credo. (Dovrebbe controllare però.) Questo non sarebbe d'aiuto con 'as' però. –

+1

Hey @Jon che funzionerebbe, non c'è bisogno di controllare. –

+0

In altre parole, il cast funzionerebbe solo se il parametro è effettivamente un'istanza di 'string' in quel momento? – MarioDS

2

Immaginate che un operatore di conversione implicito debba essere chiamato. In questo caso, qualsiasi chiamata

var castObj = rawObj as SomeType;

richiederebbe al runtime .NET di utilizzare la riflessione per determinare se l'oggetto "rawObj" ha un operatore di conversione. Ovviamente, questo sarebbe molto più dispendioso dal punto di vista computazionale piuttosto che solo per verificare se l'oggetto è di tipo SomeType o il suo sottotipo. Meglio avere un operatore veloce e prevedibile rispetto a uno più versatile, ma molto più lento.

Problemi correlati