Frage

Abschnitt 6.1 Implizite Konvertierungen definiert eine Identität Umwandlung thusly:

Eine Identität Konvertierung wandelt von jeder Art auf die gleiche Art. Diese Umwandlung existiert, so dass ein Unternehmen, das bereits hat, kann ein erforderlicher Typ diese Art sein umwandelbar gesagt werden.

Nun, was ist der Zweck der Sätze wie diese?

(In §6.1.6 Implizite Referenzkonvertierungen)

Die implizite Referenz Umwandlungen sind:

  • [...]
  • Von jedem Referenz-Typ zu einem Referenz-Typ T wenn es hat eine implizite Identität oder Referenz Umwandlung in einen Referenz-Typ T 0 und T 0 hat eine Identität Umwandlung in T.

und

(In §6.1.7 Boxen Conversions)

  • Ein Wert Typ hat eine Box-Umwandlung in einem I Interface-Typ, wenn es eine Box-Konvertierung in einen Schnittstellentyp I hat 0 und I 0 hat eine Identität Umwandlung in I .

Zunächst scheinen sie redundant (tautologisch). Aber sie müssen für einen Zweck da sein, also warum sind sie da?

Können Sie ein Beispiel von zwei Typen T geben 1 , T 2 , so dass T 1 würde nicht zu T implizit konvertierbar sein 2 , wenn es nicht für die oben genannten Absätze ist?

War es hilfreich?

Lösung

Abschnitt 4.7 der Spezifikation stellt fest, dass es eine Identität Umwandlung von Foo<dynamic> zu Foo<object> und vice versa. Der Teil der Spezifikation wird von Ihnen zitierten geschrieben, um sicherzustellen, dass dieser Fall behandelt wird. Das heißt, wenn es eine implizite Referenzkonvertierung von T zu C<object, object> ist, dann gibt es auch eine implizite Referenzkonvertierung auf C<object, dynamic>, C<dynamic, object> und C<dynamic, dynamic>.

Man könnte vernünftigerweise darauf hin, dass (1) die Absicht, diese Sätze nicht offensichtlich ist - daher Ihre Frage - und verwirrend, und (2), dass der Abschnitt über die Identität Conversions sollte den Abschnitt über die dynamischen Conversions Querverweise und ( 3) Sätze wie diese in der Spezifikation macht es schwierig für einen Implementierer der Spezifikation deutlich die spec Sprache in eine Implementierung zu übersetzen. Wie soll man wissen, ob eine solche Art existiert? Die Spezifikation muss nicht exakt Algorithmen angeben, aber es wäre schön, wenn es mehr Orientierung gibt.

Die Spezifikation ist leider kein perfektes Dokument.

Andere Tipps

Update auf 22-Sep-2010:

ich Zweifel jemand wird dies neben Timwi lesen. Trotzdem wollte ich ein paar Änderungen an diese Antwort angesichts der Tatsache machen, dass eine neue Antwort wird jetzt angenommen und die Debatte geht weiter noch (zumindest in meiner vielleicht imaginären Welt) auf, ob die zitierten Auszüge aus der Spezifikation technisch redundant sind. Ich füge nicht viel, aber es ist zu wesentlichen in einem Kommentar zu passen. Der Großteil des Update kann unter der Überschrift gefunden werden "Conversion Einbeziehung des dynamic Typs" unten.


Update auf 19-Sep-2010:

Ihr Kommentar:

[T] sein macht keinen Sinn.

Verdammt, Timwi, sagen Sie, dass viel . Aber alles in Ordnung, dann; Sie mich in die Defensive gedrängt haben, so hier geht!

Disclaimer: Ich habe auf jeden Fall nicht sucht die Spezifikation so genau wie Sie haben. Basierend auf einige Ihrer letzten Fragen scheint es, wie Sie schon in letzter Zeit in sie ein bisschen suchen. Das wird natürlich Sie besser vertraut mit vielen Details machen als die meisten Nutzer auf SO; so ist dies, wie die meisten Antworten, die Sie wahrscheinlich von einer anderen Person als Eric Lippert empfangen sind, können Sie nicht zufrieden stellen.

Verschiedene Räumlichkeiten

Zum einen ist die Prämisse Ihrer Frage, dass, wenn die markierten Aussagen überflüssig , dann dienen sie keine Zweck . Meine Antwort Prämisse ist, dass redundante Aussagen sind nicht unbedingt ohne Zweck, wenn sie etwas klarstellen, dass nicht für jedermann offensichtlich ist, . Dies sind widersprüchlich Räumlichkeiten. Und wenn wir nicht auf dem Gelände einigen können, können wir nicht einfach logisches Argument haben. Ich war einfach zu fragen Sie Ihre Prämisse zu überdenken.

Ihre Antwort war jedoch auf reite Ihre Prämisse: „Wenn die Sätze wirklich überflüssig sind, dann nur sie den Leser verwirren und alles klären nicht“

(Ich mag, wie Sie sich gesetzt als Vertreter sich für alle Leser der Spezifikation gibt, übrigens.)

Ich kann Ihnen nicht die Schuld dieser Position zu halten, genau. Ich meine, es ist scheint offensichtlich. Und ich gebe brachte keine konkreten Beispiele in meiner ursprünglichen Antwort. So unten Ich werde versuchen, einige konkrete Beispiele zu schließen. Aber zuerst, lassen Sie mich einen Schritt zurück und bieten mein nehmen auf, warum diese seltsame Identität Umwandlung Konzept besteht in der Spezifikation an erster Stelle.

Der Zweck der Identität Umwandlung Definition

Auf den ersten Blick scheint diese Definition eher überflüssig; es ist nicht einfach zu sagen, dass eine Instanz von jeder Art T umwandelbar ist ... na ja, zu T? Ja, so ist es. Aber ich hypothesize *, dass der Zweck dieser Definition ist die Spezifikation mit dem richtigen Vokabular zu schaffen, das Konzept der Typ Identität im Zusammenhang mit der Diskussion Conversions zu nutzen.

Dies ermöglicht Aussagen über Umwandlungen, die im Wesentlichen in der Natur transitiv sind. Der erste Punkt, den Sie von der Spezifikation als Beispiel für eine tautologische Aussage zitiert fällt in diese Kategorie. Er sagt, dass, wenn eine implizite Konvertierung für eine Art definiert wird auf einen anderen Typ T (ich es K nennen werde) 0 und T 0 hat eine Identität Umwandlung in T, dann K implizit konvertierbar T. Durch die Definition von ist Identität Umwandlung oben gegeben „eine Identität Umwandlung in“ wirklich bedeutet „ist die gleiche Art wie.“ So ist die Aussage überflüssig .

Aber noch einmal: die Identität Umwandlung Definition existiert in erster Linie die Spezifikation mit einer formalen Sprache auszustatten zur Beschreibung Conversions , ohne die Dinge zu sagen wie „wenn T < sub> 0 und T ist wirklich die gleiche Art. "

OK, Zeit für konkrete Beispiele.

Wo die Existenz einer impliziten Umwandlung Macht nicht offensichtlich sein, einige Entwickler

Hinweis: Eine viel besser Beispiel wird von Eric Lippert in seine Antwort auf die Frage . Ich lasse diese ersten beiden Beispiele als nur geringe Verstärkungen meines Punktes. Ich habe auch ein drittes Beispiel hinzugefügt, die die Identität Umwandlung konkretisiert, die zwischen object und dynamic wie erwähnt in Erics Antwort.

existiert

Transitive Referenzkonvertierung

Angenommen, Sie haben zwei Arten, M und N, und Sie haben eine implizite Konvertierung wie folgt definiert habe:

public static implicit operator M(N n);

Dann können Sie schreiben Code wie folgt:

N n = new N();
M m = n;

Lassen Sie uns jetzt sagen, Sie haben eine Datei mit diesem using Anweisung oben oben angelangt:

using K = M;

Und dann haben Sie später in der Datei:

N n = new N();
K k = n;

OK, bevor ich gehe, ich merke, dass dies offensichtlich ist Sie und ich . Aber meine Antwort ist, und wurde von der Anfang, dass es vielleicht nicht offensichtlich alle , und die Angabe es daher - während überflüssig - noch hat einen Zweck .

Das Zweck ist: zu jedem klar zu machen seinen Kopf kratzen, an diesem Code sucht, ist es legal. An implizite Konvertierung existiert von N auf M und ein Identitätsumwandlung besteht aus M bis K (das heißt, M und K ist der gleiche Typ); so eine implizite Konvertierung von N bis K. existiert, ist es nicht nur logischen (obwohl es sein logische); es ist direkt in der spec . Andernfalls könnte man fälschlicherweise glauben, dass so etwas wie die folgenden wäre notwendig:

K k = (M)n;

Natürlich ist es nicht.

Transitive Boxen Umwandlung

Oder nehmen Sie den Typ int. Ein int kann als IComparable<int>, richtig verpackt werden? Das ist also legal:

int i = 10;
IComparable<int> x = i;

Nun ist diese betrachten:

int i = 10;
IComparable<System.Int32> x = i;

Auch hier ja , kann es offensichtlich Sie, ich und 90% aller Entwickler, die jemals über sie kommen könnten. Aber für die schlanke Minderheit, die es nicht sehen sofort: a Boxen Umwandlung besteht aus int zu IComparable<int> und eine Identität Umwandlung besteht aus IComparable<int> zu IComparable<System.Int32> (dh IComparable<int> und IComparable<System.Int32> vom gleichen Typ ist); so eine Box-Konvertierung besteht aus int zu IComparable<System.Int32>.

Konvertierung der dynamic Typ Einbeziehung

Ich werde oben von meinem Referenzumsetzungs Beispiel leihen und es nur zwicken leicht die Identität Beziehung zwischen object und dynamic in der Version 4.0 der Spezifikation erläutern.

Lassen Sie uns sagen, dass wir die Typen M<T> und N haben, und haben irgendwo die folgende implizite Konvertierung definiert:

public static implicit operator M<object>(N n);

Dann ist die folgende Rechts:

N n = new N();
M<dynamic> m = n;

Selbstverständlich sind die oben weit weniger klar als die beiden vorherigen Beispiele. Aber hier ist die Millionen-Dollar-Frage: würde die oben noch auch legal sein, wenn die Auszüge aus der Spezifikation in der Frage zitiert gibt es nicht (Ich werde Anruf diese Auszüge F der Kürze halber). Wenn die Antwort ja ist, dann F ist in der Tat überflüssig. Wenn nein, dann ist es nicht.

Ich glaube, die Antwort ist ja.

Betrachten wir die Definition von Identität Umwandlung , definiert in Abschnitt 6.1.1 (Ich schließe den gesamten Abschnitt hier, da es recht kurz ist):

Eine Identität Konvertierung wandelt von jeder Art auf die gleiche Art. Diese Umwandlung existiert, so dass ein Unternehmen, das bereits hat, kann ein erforderlicher Typ diese Art sein umwandelbar gesagt werden.

Da object und dynamic gelten als equiwertigen gibt es eine Identität Umwandlung zwischen object und dynamic, und Typen zwischen aufgebaut, die gleich sind, wenn alle Vorkommen von dynamic mit object zu ersetzen. [Hervorhebung von mir]

(Dieser letzte Teil auch im Abschnitt 4.7 enthalten ist, die den dynamic Typ definiert.)

Jetzt ist wieder auf den Code schauen lassen. Insbesondere ist ich in dieser einer Linie interessiert:

M<dynamic> m = n;

Die Rechtmäßigkeit dieser Aussage (abgesehen von F - denken Sie daran, das Thema diskutiert wird, ist die hypothetische Rechtmäßigkeit der obigen Aussage , wenn F tat nicht exist), da M<T> und N benutzerdefinierte Typen sind, auf die Existenz eines benutzerdefinierten implizite Konvertierung zwischen N und M<dynamic> abhängig ist.

Es gibt eine implizite Konvertierung von N zu M<object>. Durch den Abschnitt der Spezifikation oben zitierten, gibt es eine Identität Umwandlung zwischen M<object> und M<dynamic>. Durch die Definition von Identität Umwandlung , M<object> und M<dynamic> ist der gleiche Typ .

So, wie in den ersten beiden (deutlicher) Beispiele, ich glaube, es ist wahr, dass eine implizite Konvertierung von N zu M<dynamic> existiert auch ohne nehmen Q Rechnung , so wie es, dass eine implizite Konvertierung besteht aus N zu K im ersten Beispiel, und dass eine Box-Konvertierung besteht aus int zu IComparable<System.Int32> im zweiten Beispiel der Fall ist.

Ohne F , das ist viel weniger offensichtlich (daher F 's Existenz); , aber das macht es nicht false (das heißt F nicht notwendig für dieses Verhalten zu definieren). Es macht es nur weniger offensichtlich.

Fazit

, sagte ich in meiner ursprünglichen Antwort, dass dies die „offensichtlich“ Erklärung dafür ist, weil es mir schien, das Sie den Holzweg. Sie stellte zunächst diese Herausforderung:

Können Sie ein Beispiel von zwei Typen T 1 , T 2 , so dass T 1 nicht implizit konvertierbar T 2 , wenn es nicht für die oben genannten Absätze?

Niemand wird diese Herausforderung gerecht zu werden, Timwi, weil es unmöglich ist. Nehmen Sie den ersten Auszug über Referenzkonvertierungen. Es ist zu sagen, dass ein Typ K auf einen Typen T implizit konvertierbar ist, wenn es implizit konvertierbar T 0 und T 0 ist das gleiche wie T. Deconstruct dies ist, es ausdrückte wieder zusammen, und Sie sind mit einer offensichtlichen Tautologie links: K ist implizit konvertierbar T, wenn es zu T. Does implizit konvertierbar ist das keine neue impliziten Konvertierungen vorstellen? Natürlich nicht.

Also vielleicht Ben Voigt Kommentar war richtig; vielleicht diese Punkte, dass Sie sind gefragt besser in den Fußnoten gesetzt würde habe, anstatt in den Körper des Textes. Auf jeden Fall ist es mir klar, dass sie sind redundant, und so mit der Prämisse zu beginnen sie nicht überflüssig sein, sonst würden sie nicht da sein ist einschiffen auf einem Narren Besorgung. Seien Sie bereit, zu akzeptieren, dass eine redundante Aussage noch etwas Licht auf einem Konzept vergießen kann, die nicht für jeden offensichtlich sein können, und es wird einfacher, diese Aussagen übernimmt für das, was sie sind.

Redundante? Ja. Tautologisch? Ja. Zwecklos? In meine Meinung, Nr.

* Natürlich, ich habe keinen Teil haben in der Sprache C # Spezifikation zu schreiben. Wenn ich das täte, würde diese Antwort viel mehr maßgebend. Wie es ist, stellt es einfach einen schwachen Versuch Kerl Sinn ein ziemlich komplexen Dokument zu machen.


Original Antwort

Ich glaube, dir (vielleicht absichtlich) mit Blick auf die naheliegendste Antwort hier.

Beachten Sie auch diese beiden Sätze in Ihrer Frage:

(1) Zunächst scheinen sie überflüssig (tautologisch). (2) Aber sie müssen es sein für einen Zweck, also warum sind sie da?

Für mich ist die Implikation dieser beiden Sätze zusammen, dass eine tautologische Aussage keinen Zweck dient. Aber nur weil eine Aussage von etablierten Prämissen logisch folgt, bedeutet das nicht macht es für jeden offensichtlich. Mit anderen Worten, selbst wenn (1) ist wahr, die Antwort auf (2) kann einfach sein: das beschriebene Verhalten machen jedem klar Lesen die Spezifikation .

Nun könnte man, dass sogar argumentieren, wenn etwas nicht klar , tut es immer noch nicht, gehört in einer Spezifikation, wenn es eine redundante Definition bereitstellt. Um dieses Potenzial Einwand, kann ich nur sagen: realistisch sein. Es ist nicht wirklich praktisch (meiner Meinung nach) zu kämmen durch ein Dokument alle Aussagen Strippen, die einfach unter Angabe Tatsachen sind, die aus vorherigen Aussagen abgeleitet werden können.

Wenn diese waren eine gängige Praxis, denke ich Ihnen viel Literatur gibt, finden würde - nicht nur Spezifikationen, aber die Forschung Papiere, Artikel, Lehrbücher usw. - wäre ein viel kürzer, dichter und schwerer zu verstehen.

Also: ja, vielleicht sind sie überflüssig. Aber das negiert nicht ihren Zweck.

Eine Identität Umwandlung wandelt jede Art auf die gleiche Art . Dies Umwandlung existiert, so dass eine Entität dass bereits einen erforderlichen Typ Dose gesagt werden, dass sein umwandelbar Art.

Diese besagen, dass in C # -Land, 1 == 1; ein Spaten ist ein Spaten. Dies ist die Grundlage einer Variablen des gleichen Typs eine Objektreferenz zuzuweisen; Wenn eine Variable T1 eingegeben und eine typisierte T2 in Wirklichkeit sind die beiden Spaten, ist es möglich, assign einem zum anderen ohne explizit mit einem Guss als Spaten. Stellen Sie sich eine C # Variante, bei Zuweisungen wie folgt aussehen hatte:

Spade mySpade = new Spade();
Spade mySpade2;

mySpade2 = (Spade)mySpade; //explicit cast required

Auch eine „Identität“ in der Mathematik besagt, dass ein Ausdruck, dass Ergibt ein Ergebnis eine Satz von Eingängen gegeben ist äquivalent zu einem anderen Ausdruck, der das gleiche Ergebnis erzeugt die gleichen Eingänge gegeben. In der Programmierung Dies bedeutet, dass ein Ausdruck auswertet oder Funktion, die mit einer Instanz eines Typs, in diesem Typ äquivalent ist, ohne explizite Umwandlung. Wenn das nicht halten, würde der folgende Code erforderlich:

public int myMethod() { /*Do something*/ }
...
int myInt = (int)myMethod(); //required even though myMethod() evals to an int.
...
int myInt = (int)(1 + 2); //required even though 1, 2, and 1+2 eval to an int.

Die zweite Regel besagt im Grunde, dass ein Werttyp kann auf einer Klasse zu einer Membervariable zugeordnet werden, wenn zum Teil der Membervariablen (eine Box Art definitions als Behälter ein Referenztyp ist) deklariert wird die sein, dieselbe Art. Wenn diese Regel nicht angegeben wurden, theoretisch könnte eine Version von C # gibt, in denen reine Werttypen müssen explizit auf ihre Referenz analog umgewandelt, um würde als Member-Variable auf eine Klasse gespeichert werden. Stellen Sie sich zum Beispiel eine Version von C #, in dem die blauen Keyword-Typen (int, float, dezimal) und die hellblauen Klassennamen (Int32, Float, Dezimal) bezeichnet zwei sehr unterschiedliche, nur-explizit wandelbare Typen und int , Schwimmer, dezimal usw. als Mitglied Variablentypen nicht legal waren, weil sie nicht Referenztypen waren:

public class MyClass
{
  Int32 MyBoxedValueType; //using "int" not legal
}

...

MyClass myClass = new MyClass();
int theInt = 2;

myClass.MyBoxedValueType = (Int32)theInt; //explicit cast required

Ich weiß, es klingt albern, aber auf einer gewissen Ebene müssen diese Dinge bekannt sein und in Computern, haben Sie alles zu spezifizieren. Lesen Sie die USA Hockey rulebook für Eishockey irgendwann; die erste Regel in dem Buch ist, dass das Spiel auf einer Eisfläche gespielt werden soll. Es ist eine des letzten „gut Duhs“, sondern auch eine grundlegende Wahrheit des Spiels, das für jede andere Regel, um zu verstehen, muss Sinn machen.

Mai ist es so, dass die Code-Garantien Pass-Through, wenn sie aufgerufen wie Convert.ChangeType(client, typeof(Client)) unabhängig davon, ob IConvertible umgesetzt wird.

Schauen Sie in die Quelle der ChangeType von mscorlib mit Reflektor und beachten Sie die Bedingungen, bei denen value zurückgeführt wird, wie sie ist.

Denken Sie daran, ein = Operator nicht eine Umwandlung ist, nur ein Referenzsatz. So Code wie Client client_2 = client_1 keine impliziten Konvertierungen durchführt. Wenn eine Identität implizite Konvertierung deklariert wird, so wird der Fehler CS0555 ausgegeben.

Ich denke, die Spezifikation sagt lassen die C # -Compiler Griff solchen Fällen und damit dot nicht manuell versuchen Identität Conversions zu definieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top