2012-05-23 7 views
8

In seinem Buch bezieht sich Jon Skeet auf 7 Einschränkungen impliziter Typisierung. Ich brauche eine Klarstellung zu den letzten zwei:Einschränkungen bei impliziter Typisierung

A. Der Typ, den die Variable haben soll, ist der Kompilierungszeittyp des Initialisierungsausdrucks.
B. Der Initialisierungsausdruck bezieht die Variable nicht mit ein.

Das Buch umfasst Material in der gleichen Reihenfolge, in der es veröffentlicht wurde (C# 2 vor C# 3). An diesem Punkt wurde C# 4 nicht eingeführt, daher nehme ich an, dass sich A nicht auf dynamic bezieht. Wann würde sich also der Kompilierzeittyp vom Ausführungszeittyp des Initialisierungsausdrucks unterscheiden?

Wie für B, wann kann ein Initialisierungsausdruck die Variable deklarieren?

+0

Ist 'var x = 2 * x' kein gutes Beispiel für ** B **? –

+0

@WiktorZychla - das würde auch nicht mit expliziter Typisierung kompilieren. –

+0

Ein Beispiel für A: 'var x = (Objekt) string.Empty;' – phoog

Antwort

3

Bezüglich B gab Henk eine perfekte Antwort (edit: es ist jetzt entfernt), obwohl ich es seltsam finde, dass int x = x = 1; kompiliert. (Ich habe gedacht, x gilt erst nach dem initializer erklärt Oh, gut..) Seine Antwort war:

int x = x = 1; // Compiles 
var y = y = 2; // Does not compile 

In Bezug auf Eine und Ihre Frage, wann die Kompilierung Typ wouldn ‚t die Ausführungszeit Typ entsprechen, hier ist ein Beispiel, wo sie sich unterscheiden würde:

var foo = fooFactory.GetFoo(); 

... und das Verfahren auf FooFactory implementiert als ....

public FooBase GetFoo() { 
    return new FooSubtype(); 
} 

Hier foo ‚s-Typ ist FooBase und (ohne Guss) (die eine Schnittstelle, abstrakte Klasse oder entsiegelt konkrete Klasse sein kann) nur sind seine Funktionen zur Verfügung. Offensichtlich implementiert oder erbt FooSubtype von FooBase.

Die Art, dass foo zur Laufzeit erkennen kann nur hier halten, weil ich die Implementierung von getFoo() zeigen, aber es vom Compiler nicht kontrolliert wird. Tatsächlich ist die Implementierung möglicherweise nicht einmal verfügbar (könnte in einer anderen Assembly sein) oder sie kann variieren (könnte virtuell sein). Zur Ermittlung des Kompilierzeittyps von GetFoo() und damit von foo ist nur die Methodendeklaration relevant.

+0

Sie haben meine Stimme für eine sehr klare Erklärung, aber in diesem Fall muss die explizite Deklaration auch "FooBase a" und nicht "FooSubtype a" sein, so dass es keinen Vorteil bietet, die explizite Deklaration zu verwenden. Ich denke, die Einschränkung bezieht sich auf eine explizite Deklaration. –

+0

Danke für Upvote, @AlejandroPiad! Aber ich denke "Einschränkungen" beziehen sich darauf, wenn die implizite Deklaration ** möglich ist **. D. h., Wenn Ihr Initialisierungsausdruck einen von ihnen verletzt, dann können Sie keine implizite Deklaration verwenden. Ob es bevorzugt ist, ist eine andere Sache mit unterschiedlichen Meinungen. –

+0

Fair genug. Bevorzugt ist das falsche Wort. Ich habe versucht, etwas zu sagen, wenn implizite Typisierung Ihnen einen Vorteil bringt, aber hey, Sie haben absolut Recht, das wäre eine Meinungsfrage. –

2

Meine Gedanken für A:

Es ist nicht, dass die Übersetzungszeit vom Ausführungstyp unterschiedlich ist, da selbst dann, wenn die Ausführung Typ in jedem Verfahren nicht das gleiches wie der Compilertyp (wie deren Rückkehr type ist ein abstrakter Typ), die Variable mit dem Ausführungstyp kann bei expliziter Typisierung trotzdem nicht deklariert werden.

Aber Sie könnten die Variable mit einem abstrakteren statischen Typ deklarieren möchten, auch wenn der echte dynamischen Typ zur Kompilierzeit definiert werden kann. Betrachten Sie zum Beispiel:

ISomething a = new MyOwnSomething(); 

Warum möchten Sie dies tun? Wenn Ihr MyNewSomething explizit ISomething implementiert, dann müssten Sie einen Cast erstellen, um es wie ein ISomething zu verwenden, wenn es auf einem Var deklariert wird. Hier ist die Besetzung noch getan worden, aber Sie nicht sehen, die eher hässlich:

var a = new MyOwnSomething(); 
((ISomething)a).Whatever(); 

Ein konstruiertes Beispiel ist, dass der Code Initialisierung später aber ändern können und Sie sicherstellen möchten, dass von diesem Zeitpunkt an Sie verwenden nur a als ISomething, und nie die Details des Typs MyOwnSomething oder andere Schnittstellen zu sehen, die es möglicherweise implementiert, so dass Änderungen am Initialisierungstyp den Code nicht brechen.

+1

Ein anderes Beispiel wäre eine Variable, die auf einen bestimmten Typ initialisiert wird, aber in ihrer Lebensdauer andere weniger spezifische Typen haben kann. – supercat

+1

Sie können immer sagen 'var a = (ISomething) neu MyOwnSomething();' – phoog

+0

@phoog: Genau. Das ist es, was die explizite Deklaration mit einer etwas netteren Syntax für Sie löst. –