2016-10-31 3 views
3

Betrachten Sie das folgende Beispiel:Erfolgt die Typrückgabe von rechts nach links?

public class Person 
{ 
    public int Age { get; set; } 
} 

public class Builder<TSource> 
{ 
    public Builder<TSource> WithValue<TValue>(Func<TSource, TValue>, TValue value) 
    { 
     // ... 
    } 
} 

Diese beiden Linien arbeiten und laufen gerade fein:

Builder<Person> builder = new Builder<Person>(); 
builder.WithValue(p => p.Age, 20); 

Aber so diese tun:

Builder<Person> builder = new Builder<Person>(); 
object age = "20";        // <-- string value 
builder.WithValue(p => p.Age, age); 

Typ-Inferenz nicht die Art und Weise arbeitet I erwarte es am letzten Beispiel zu arbeiten.

Wenn ich einen Ausdruck p => p.Age angeben, der Func<Person, int> ist, erwarte ich, dass das zweite Argument auf einen int-Typ beschränkt ist. Dennoch bin ich in der Lage, eine object gut zu übergeben.

Ich vermute, das liegt daran, dass Typ Rückschluss von rechts nach links gemacht wird. Das heißt, Argument wird als object und dann meine Func<TSource, TValue> Ausdruck wird auf eine Func<Person, object> beschränkt, die p => p.Age erfüllt nur gut.

Ist meine Annahme richtig?

Wenn ja, warum wird Typinferenz auf diese Weise durchgeführt? Ich finde es natürlicher von links nach rechts.

Antwort

5

Es ist nicht auftragsabhängig überhaupt. Der Parameter p => p.Age fügt die Einschränkung hinzu, dass unabhängig von TValue ein Typ sein muss, der eine int speichern kann. Das könnte int oder ein beliebiger Typ sein, von dem er erbt, wie beispielsweise object. Wenn Sie übergeben, sagen Sie, dass TValue ein Typ sein muss, der eine object speichern kann. Es wählt dann den am weitesten abgeleiteten Typ aus, der alle diese Einschränkungen erfüllt, in diesem Fall object. Das Gleiche würde passieren, wenn Sie die Reihenfolge der Parameter ändern.

+0

Ist nicht der am weitesten abgeleitete Typ 'int'? –

+0

@MatiasCicero Der Typ 'int' erfüllt nicht beide Bedingungen; es erfüllt nur eine der beiden Bedingungen, da Sie ein 'Objekt' in einer Variablen vom Typ 'int' nicht speichern können. – Servy

+0

Ich glaube, ich verstehe es jetzt. Danke für die schnelle Antwort! –

1

Es ist weder von links nach rechts noch von rechts nach links. Typ-Inferenz nimmt die Typinformationen, die in der gegebenen Situation verfügbar sind, und versucht herauszufinden, welcher Typ ersetzt werden kann, so dass er mit allen entsprechenden Ausdrücken kompatibel ist. Dies wird typischerweise von dem nächsten gemeinsamen Vorfahren erfüllt. In Ihrem Fall haben sowohl int als auch objectobject als diesen nächsten gemeinsamen Vorfahren. Im Allgemeinen kann die Auflösung jedoch aufgrund von Schnittstellen etwas komplizierter sein.

Verwandte Themen