Wofür wird der 'dynamische' Typ in C # 4.0 verwendet?

236

In C # 4.0 wurde ein neuer Typ namens "dynamisch" eingeführt. Es klingt alles gut, aber wofür würde ein Programmierer es verwenden?

Gibt es eine Situation, in der es den Tag retten kann?

Fahad
quelle
4
mögliches Duplikat von stackoverflow.com/questions/2255982/…
Jörg W Mittag
Dies ist nützlich, wenn Sie mit COM oder dynamisch typisierten Sprachen arbeiten. Wenn Sie beispielsweise lua oder python zum Erstellen von Skripten für Ihre Sprache verwenden, ist es sehr praktisch, den Skriptcode so aufzurufen, als wäre es normaler Code.
CodesInChaos
Ich hoffe, dieser Artikel hat vollständige Antwort auf Ihre Frage visualstudiomagazine.com/Articles/2011/02/01/…
Entwickler

Antworten:

196

Das dynamische Schlüsselwort ist neu in C # 4.0 und wird verwendet, um dem Compiler mitzuteilen, dass sich der Typ einer Variablen ändern kann oder dass er erst zur Laufzeit bekannt ist. Stellen Sie sich vor, Sie könnten mit einem Objekt interagieren, ohne es wirken zu müssen.

dynamic cust = GetCustomer();
cust.FirstName = "foo"; // works as expected
cust.Process(); // works as expected
cust.MissingMethod(); // No method found!

Beachten Sie, dass wir cust nicht als Typ Kunde deklarieren oder deklarieren mussten. Da wir es als dynamisch deklariert haben, übernimmt die Laufzeit und sucht und legt die FirstName-Eigenschaft für uns fest. Wenn Sie jetzt eine dynamische Variable verwenden, geben Sie natürlich die Überprüfung des Compilertyps auf. Dies bedeutet, dass der Aufruf cust.MissingMethod () kompiliert wird und erst zur Laufzeit fehlschlägt. Das Ergebnis dieser Operation ist eine RuntimeBinderException, da MissingMethod in der Customer-Klasse nicht definiert ist.

Das obige Beispiel zeigt, wie dynamisch beim Aufrufen von Methoden und Eigenschaften funktioniert. Eine weitere leistungsstarke (und möglicherweise gefährliche) Funktion ist die Wiederverwendung von Variablen für verschiedene Datentypen. Ich bin mir sicher, dass die Programmierer von Python, Ruby und Perl sich eine Million Möglichkeiten vorstellen können, dies zu nutzen, aber ich habe C # so lange verwendet, dass es sich für mich einfach "falsch" anfühlt.

dynamic foo = 123;
foo = "bar";

OK, Sie werden also wahrscheinlich nicht sehr oft Code wie den oben genannten schreiben. Es kann jedoch vorkommen, dass die variable Wiederverwendung nützlich sein oder einen schmutzigen Teil des Legacy-Codes bereinigen kann. Ein einfacher Fall, auf den ich oft stoße, ist das ständige Umschalten zwischen Dezimal und Doppel.

decimal foo = GetDecimalValue();
foo = foo / 2.5; // Does not compile
foo = Math.Sqrt(foo); // Does not compile
string bar = foo.ToString("c");

Die zweite Zeile wird nicht kompiliert, da 2.5 als Double eingegeben wird, und Zeile 3 wird nicht kompiliert, da Math.Sqrt ein Double erwartet. Natürlich müssen Sie nur Ihren Variablentyp umwandeln und / oder ändern, aber es kann Situationen geben, in denen die Verwendung von Dynamik sinnvoll ist.

dynamic foo = GetDecimalValue(); // still returns a decimal
foo = foo / 2.5; // The runtime takes care of this for us
foo = Math.Sqrt(foo); // Again, the DLR works its magic
string bar = foo.ToString("c");

Weitere Informationen finden Sie unter: http://www.codeproject.com/KB/cs/CSharp4Features.aspx

Pranay Rana
quelle
96
Persönlich mag ich den Gedanken nicht, das dynamicin c # zum Lösen von Problemen zu verwenden, die durch Standard-c # -Funktionen und statische Typisierung oder höchstens mit Typinferenz ( var) gelöst werden können (vielleicht sogar noch besser ). dynamicsollte nur verwendet werden, wenn es um Interoperabilitätsprobleme mit dem DLR geht. Wenn Sie Code in einer statisch typisierten Sprache wie c # schreiben, tun Sie dies und emulieren Sie keine dynamische Sprache. Das ist einfach hässlich.
Philip Daubmeier
40
Wenn Sie dynamicVariablen in Ihrem Code stark nutzen, wo Sie sie nicht benötigen (wie in Ihrem Beispiel mit dem Squareroot), geben Sie die Fehlerprüfung bei der Kompilierungszeit auf. Stattdessen erhalten Sie jetzt mögliche Laufzeitfehler.
Philip Daubmeier
33
Meistens in Ordnung, aber ein paar kleinere Fehler. Erstens ist es nicht richtig zu sagen, dass dynamisch bedeutet, dass sich der Variablentyp ändern kann. Die fragliche Variable ist vom Typ "dynamisch" (aus Sicht der C # -Sprache; aus Sicht der CLR ist die Variable vom Typ Objekt). Der Typ einer Variablen ändert sich nie . Der Laufzeittyp des Werts einer Variablen kann ein beliebiger Typ sein, der mit dem Typ der Variablen kompatibel ist. (Oder im Fall von Referenztypen kann es null sein.)
Eric Lippert
15
Zu Ihrem zweiten Punkt: C # hatte bereits die Funktion "Variable erstellen, in die Sie alles einfügen können" - Sie können jederzeit eine Variable vom Typ Objekt erstellen. Das Interessante an der Dynamik ist, worauf Sie in Ihrem ersten Absatz hinweisen: Die Dynamik ist nahezu identisch mit dem Objekt, mit der Ausnahme, dass die semantische Analyse bis zur Laufzeit verschoben wird und die semantische Analyse für den Laufzeittyp des Ausdrucks durchgeführt wird. (Meistens. Es gibt einige Ausnahmen.)
Eric Lippert
18
Ich habe einen Abstimmungspunkt dafür ausgegeben, hauptsächlich, weil implizit die Verwendung des Schlüsselworts für den allgemeinen Gebrauch befürwortet wird. Es hat einen spezifisch zielgerichteten Zweck (perfekt beschrieben in Lasses 'Antwort) und obwohl diese Antwort technisch korrekt ist, wird sie Entwickler wahrscheinlich in die Irre führen.
Acht-Bit-Guru
211

Das dynamicSchlüsselwort wurde zusammen mit vielen anderen neuen Funktionen von C # 4.0 hinzugefügt, um die Kommunikation mit Code zu vereinfachen, der in anderen Laufzeiten mit unterschiedlichen APIs lebt oder von diesen stammt.

Nehmen Sie ein Beispiel.

Wenn Sie ein COM-Objekt wie das Word.ApplicationObjekt haben und ein Dokument öffnen möchten, enthält die entsprechende Methode nicht weniger als 15 Parameter, von denen die meisten optional sind.

Um diese Methode aufzurufen, benötigen Sie etwa Folgendes (ich vereinfache, dies ist kein tatsächlicher Code):

object missing = System.Reflection.Missing.Value;
object fileName = "C:\\test.docx";
object readOnly = true;
wordApplication.Documents.Open(ref fileName, ref missing, ref readOnly,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing, ref missing, ref missing, ref missing,
    ref missing, ref missing);

Alle diese Argumente notieren? Sie müssen diese übergeben, da C # vor Version 4.0 keine Vorstellung von optionalen Argumenten hatte. In C # 4.0 wurde die Arbeit mit COM-APIs vereinfacht, indem Folgendes eingeführt wurde:

  1. Optionale Argumente
  2. Herstellung refoptional für COM - APIs
  3. Benannte Argumente

Die neue Syntax für den obigen Aufruf wäre:

wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);

Sehen Sie, wie viel einfacher es aussieht, wie viel lesbarer es wird?

Lassen Sie uns das auseinander brechen:

                                    named argument, can skip the rest
                                                   |
                                                   v
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
                                 ^                         ^
                                 |                         |
                               notice no ref keyword, can pass
                               actual parameter values instead

Die Magie ist, dass der C # -Compiler jetzt den erforderlichen Code einfügt und zur Laufzeit mit neuen Klassen arbeitet, um fast genau das zu tun, was Sie zuvor getan haben, aber die Syntax wurde Ihnen verborgen, jetzt können Sie sich auf das konzentrieren was und nicht so sehr auf das wie . Anders Hejlsberg sagt gern, dass man verschiedene "Beschwörungsformeln" aufrufen muss, was eine Art Wortspiel für die Magie des Ganzen ist, bei dem man normalerweise mit den Händen winken und einige magische Wörter in der richtigen Reihenfolge sagen muss um eine bestimmte Art von Zauber in Gang zu bringen. Die alte API-Art, mit COM-Objekten zu kommunizieren, war eine Menge davon. Sie mussten durch viele Rahmen springen, um den Compiler zu überreden, den Code für Sie zu kompilieren.

In C # vor Version 4.0 wird es noch schlimmer, wenn Sie versuchen, mit einem COM-Objekt zu sprechen, für das Sie keine Schnittstelle oder Klasse haben IDispatch. Sie haben lediglich eine Referenz.

Wenn Sie nicht wissen, was es ist, IDispatchist im Grunde Reflexion für COM-Objekte. Mit einer IDispatchSchnittstelle können Sie das Objekt "Wie lautet die ID-Nummer für die als Speichern bekannte Methode?" Fragen, Arrays eines bestimmten Typs erstellen, die die Argumentwerte enthalten, und schließlich eine InvokeMethode auf der IDispatchSchnittstelle aufrufen, um die Methode aufzurufen, wobei alle übergeben werden die Informationen, die Sie zusammengetragen haben.

Die obige Speichermethode könnte folgendermaßen aussehen (dies ist definitiv nicht der richtige Code):

string[] methodNames = new[] { "Open" };
Guid IID = ...
int methodId = wordApplication.GetIDsOfNames(IID, methodNames, methodNames.Length, lcid, dispid);
SafeArray args = new SafeArray(new[] { fileName, missing, missing, .... });
wordApplication.Invoke(methodId, ... args, ...);

All dies, um nur ein Dokument zu öffnen.

VB hatte vor langer Zeit optionale Argumente und Unterstützung für das meiste davon, also diesen C # -Code:

wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);

ist im Grunde nur C #, das VB in Bezug auf Ausdruckskraft einholt, aber es richtig macht, indem es erweiterbar gemacht wird, und nicht nur für COM. Dies ist natürlich auch für VB.NET oder eine andere Sprache verfügbar, die auf der .NET-Laufzeit basiert.

Weitere Informationen zur IDispatchBenutzeroberfläche finden Sie auf Wikipedia: IDispatch, wenn Sie mehr darüber lesen möchten. Es ist wirklich blutiges Zeug.

Was ist jedoch, wenn Sie mit einem Python-Objekt sprechen möchten? Dafür gibt es eine andere API als die für COM-Objekte verwendete. Da Python-Objekte ebenfalls dynamischer Natur sind, müssen Sie auf Reflection Magic zurückgreifen, um die richtigen Methoden zum Aufrufen, ihre Parameter usw. zu finden, nicht jedoch das .NET Reflexion, etwas, das für Python geschrieben wurde, ziemlich ähnlich dem obigen IDispatch-Code, nur ganz anders.

Und für Ruby? Noch eine andere API.

JavaScript? Gleiches Angebot, auch dafür unterschiedliche API.

Das dynamische Schlüsselwort besteht aus zwei Dingen:

  1. Das neue Schlüsselwort in C #, dynamic
  2. Eine Reihe von Laufzeitklassen, die wissen, wie mit den verschiedenen Objekttypen umzugehen ist, die eine bestimmte API implementieren, die für das dynamicSchlüsselwort erforderlich ist, und die Aufrufe der richtigen Vorgehensweise zuordnen. Die API ist sogar dokumentiert. Wenn Sie also Objekte haben, die aus einer nicht abgedeckten Laufzeit stammen, können Sie sie hinzufügen.

Das dynamicSchlüsselwort soll jedoch keinen vorhandenen Nur-.NET-Code ersetzen. Sicher, Sie können es tun, aber es wurde aus diesem Grund nicht hinzugefügt, und die Autoren der C # -Programmiersprache mit Anders Hejlsberg an der Spitze waren äußerst fest davon überzeugt, dass sie C # immer noch als stark typisierte Sprache betrachten und nicht opfern werden dieses Prinzip.

Dies bedeutet, dass Sie zwar Code wie folgt schreiben können:

dynamic x = 10;
dynamic y = 3.14;
dynamic z = "test";
dynamic k = true;
dynamic l = x + y * z - k;

und lassen Sie es kompilieren, es war nicht als eine Art magisches System gedacht, mit dem Sie herausfinden können, was Sie zur Laufzeit gemeint haben.

Der ganze Zweck war es, es einfacher zu machen, mit anderen Arten von Objekten zu sprechen.

Im Internet gibt es viel Material über das Schlüsselwort, Befürworter, Gegner, Diskussionen, Beschimpfungen, Lob usw.

Ich schlage vor, Sie beginnen mit den folgenden Links und googeln dann für mehr:

Lasse V. Karlsen
quelle
12
Abgesehen von COM ist es auch nützlich für Web-JSON-APIs, bei denen die Struktur der de-serialisierten JSON-Objekte in C # nicht angegeben ist. Beispielsweise gibt die Decode-Methode von System.Web.Helpers.Json ein dynamisches Objekt zurück .
Dumbledad
Abgesehen von "sie betrachten C # immer noch als eine stark typisierte Sprache": Eric Lippert ist kein Fan von "stark typisiert" als Beschreibung.
Andrew Keeton
Ich bin nicht einverstanden mit ihm, aber es ist eine Ansichtssache, keine Tatsache. "Stark typisiert" bedeutet für mich, dass der Compiler zur Kompilierungszeit weiß, welcher Typ verwendet wird, und somit die Regeln erzwingt, die für diese Typen festgelegt wurden. Die Tatsache, dass Sie sich für einen dynamischen Typ entscheiden können, der die Regelprüfung und Bindung an die Laufzeit verschiebt, bedeutet für mich nicht, dass die Sprache schwach typisiert ist. Normalerweise kontrastiere ich nicht stark mit schwach getippt, aber ich vergleiche es normalerweise mit dynamisch getippten Sprachen wie Python, in denen alles eine Ente ist, bis es bellt.
Lasse V. Karlsen
Was ist der Sinn dieser Antwort? Die Hälfte davon betrifft optionale Parameter und die IDispatch-Schnittstelle.
Xam
Aus diesem Grund dynamicwurde hinzugefügt, um andere Ökosysteme dabei zu unterstützen, wie reflexionsähnliche Methodenaufrufe durchgeführt werden können, und um eine Art Black-Box-Ansatz für Datenstrukturen bereitzustellen, mit dem dies dokumentiert werden kann.
Lasse V. Karlsen
29

Ich bin überrascht, dass niemand den Mehrfachversand erwähnt hat . Die übliche Art, dies zu umgehen , ist das Besuchermuster. Dies ist nicht immer möglich, sodass Sie gestapelte isSchecks erhalten.

Hier ist ein Beispiel aus dem wirklichen Leben für eine eigene Anwendung. Anstatt zu tun:

public static MapDtoBase CreateDto(ChartItem item)
{
    if (item is ElevationPoint) return CreateDtoImpl((ElevationPoint)item);
    if (item is MapPoint) return CreateDtoImpl((MapPoint)item);
    if (item is MapPolyline) return CreateDtoImpl((MapPolyline)item);
    //other subtypes follow
    throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}

Sie machen:

public static MapDtoBase CreateDto(ChartItem item)
{
    return CreateDtoImpl(item as dynamic);
}

private static MapDtoBase CreateDtoImpl(ChartItem item)
{
    throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}

private static MapDtoBase CreateDtoImpl(MapPoint item)
{
    return new MapPointDto(item);
}

private static MapDtoBase CreateDtoImpl(ElevationPoint item)
{
    return new ElevationDto(item);
}

Beachten Sie, dass es sich im ersten Fall ElevationPointum eine Unterklasse von handelt MapPointund wenn es nicht platziert wird, bevor MapPoint es niemals erreicht wird. Dies ist bei Dynamic nicht der Fall, da die Methode mit der engsten Übereinstimmung aufgerufen wird.

Wie Sie dem Code entnehmen können, war diese Funktion praktisch, als ich die Übersetzung von ChartItem-Objekten in ihre serialisierbaren Versionen durchführte. Ich wollte meinen Code nicht mit Besuchern verschmutzen und ich wollte meine ChartItemObjekte auch nicht mit nutzlosen serialisierungsspezifischen Attributen verschmutzen .

Stelios Adamantidis
quelle
Wusste nichts über diesen Anwendungsfall. Im besten Fall ein bisschen hackig. Jeder statische Analysator wird ausgeschaltet.
Kugel
2
@ Kugel das ist wahr, aber ich würde es nicht einen Hack nennen . Die statische Analyse ist gut, aber ich würde mich nicht von einer eleganten Lösung abhalten lassen, bei der die Alternativen sind: Verletzung des Open-Closed-Prinzips (Besuchermuster) oder erhöhte zyklomatische Komplexität mit gefürchteten Stapeln isübereinander.
Stelios Adamantidis
4
Nun, Sie haben die Möglichkeit, Muster mit C # 7 abzugleichen, nein?
Kugel
2
Nun, Operatoren sind auf diese Weise viel billiger (Vermeidung von Double Cast) und Sie erhalten statische Analysen zurück ;-) und Leistung.
Kugel
@idbrii bitte ändere meine Antworten nicht. Fühlen Sie sich frei, einen Kommentar zu hinterlassen, und ich werde dies (falls erforderlich) klären, da ich immer noch in dieser Community aktiv bin. Bitte auch nicht verwenden magic; Es gibt keine Magie.
Stelios Adamantidis
11

Es erleichtert statisch typisierten Sprachen (CLR) die Zusammenarbeit mit dynamischen Sprachen (Python, Ruby ...), die auf dem DLR (Dynamic Language Runtime) ausgeführt werden (siehe MSDN) :

Beispielsweise können Sie den folgenden Code verwenden, um einen Zähler in XML in C # zu erhöhen.

Scriptobj.SetProperty("Count", ((int)GetProperty("Count")) + 1);

Bei Verwendung des DLR können Sie stattdessen den folgenden Code für denselben Vorgang verwenden.

scriptobj.Count += 1;

MSDN listet diese Vorteile auf:

  • Vereinfacht das Portieren dynamischer Sprachen in .NET Framework
  • Aktiviert dynamische Funktionen in statisch typisierten Sprachen
  • Bietet zukünftige Vorteile von DLR und .NET Framework
  • Ermöglicht die gemeinsame Nutzung von Bibliotheken und Objekten
  • Bietet schnellen dynamischen Versand und Aufruf

Weitere Informationen finden Sie unter MSDN .

Philip Daubmeier
quelle
1
Und die für die Dynamik erforderliche Änderung der VM erleichtert dynamische Sprachen.
Dykam
2
@Dykam: Es gibt keine Änderung an der VM. Das DLR funktioniert bis zu .NET 2.0 einwandfrei.
Jörg W Mittag
@ Jörg, ja es gibt eine Änderung. Das DLR wird teilweise neu geschrieben, da die VM jetzt Unterstützung für dynamische Auflösung bietet.
Dykam
Ich war ein bisschen zu optimistisch, Untersuchungen haben gezeigt, dass die Veränderungen nicht so groß waren.
Dykam
4

Ein Anwendungsbeispiel:

Sie verwenden viele Klassen mit der kommunalen Eigenschaft 'CreationDate':

public class Contact
{
    // some properties

    public DateTime CreationDate { get; set; }        
}

public class Company
{
    // some properties

    public DateTime CreationDate { get; set; }

}

public class Opportunity
{
    // some properties

    public DateTime CreationDate { get; set; }

}

Wenn Sie eine Kommunikationsmethode schreiben, die den Wert der Eigenschaft 'CreationDate' abruft, müssen Sie Reflection verwenden:

    static DateTime RetrieveValueOfCreationDate(Object item)
    {
        return (DateTime)item.GetType().GetProperty("CreationDate").GetValue(item);
    }

Mit dem "dynamischen" Konzept ist Ihr Code viel eleganter:

    static DateTime RetrieveValueOfCreationDate(dynamic item)
    {
        return item.CreationDate;
    }
Akli
quelle
7
Ente tippt, nett. Sie sollten hierfür jedoch eine Schnittstelle verwenden, wenn dies Ihre Typen sind.
Kugel
3

COM interop. Besonders unbekannt. Es wurde speziell dafür entwickelt.

Aen Sidhe
quelle
2

Es wird hauptsächlich von RAD- und Python-Opfern verwendet, um die Codequalität, IntelliSense und die Fehlererkennung bei der Kompilierung zu zerstören .

Stormianrootsolver
quelle
Eine zynische Antwort, aber leicht zu wahr. Ich habe es einfach getan, um zu vermeiden, dass Strukturen deklariert werden, mit dem Ergebnis, dass der Code funktioniert, wenn alles in Ordnung ist, aber seinen Stapel auf unvorhersehbare Weise aufbläst, sobald Sie den Käse verschieben.
AnthonyVO
Ja, Sie werden diesen klassischen Eckschnitt mit vielen anderen Sprachfunktionen sehen. Es ist keine Überraschung, dass Sie es auch hier sehen würden.
Hawkeye4040
1

Es wird zur Laufzeit ausgewertet, sodass Sie den Typ wie in JavaScript nach Belieben ändern können. Das ist echt:

dynamic i = 12;
i = "text";

Und so können Sie den Typ nach Bedarf ändern. Verwenden Sie es als letzten Ausweg; Es ist von Vorteil, aber ich habe gehört, dass in Bezug auf die generierte IL unter den Kulissen viel passiert, und das kann zu einem Leistungspreis führen.

Brian Mains
quelle
7
Ich würde zögern zu sagen, dass es "legitim" ist. Es wird sicherlich kompiliert, so dass es als solches "legitimer Code" in dem Sinne ist, dass der Compiler es jetzt kompiliert und die Laufzeit es ausführt. Aber ich würde niemals diesen bestimmten Code (oder etwas Ähnliches) in einem der von mir gepflegten Codes sehen wollen, oder es wäre eine beinahe feuernde Straftat.
Lasse V. Karlsen
6
Sicher, aber das wäre "legitim" mit "Objekt" statt "dynamisch" gewesen. Sie haben hier nichts Interessantes über Dynamik gezeigt.
Eric Lippert
Für ein Objekt müssten Sie es in den entsprechenden Typ umwandeln, um tatsächlich eine seiner Methoden aufzurufen ... Sie verlieren die Signatur; Sie können Ihren Code jede Methode aufrufen lassen, ohne dass ein Kompilierungsfehler auftritt, und dieser Fehler tritt zur Laufzeit auf. Ich hatte es eilig, etwas zu tippen. Und @Lasse, ich würde zustimmen und ich werde wahrscheinlich nicht viel Dynamik verwenden.
Brian Mains
1
Der Anwendungsfall des letzten
Auswegs
1

Der beste Anwendungsfall für Variablen vom Typ 'dynamisch' war für mich, als ich kürzlich eine Datenzugriffsschicht in ADO.NET ( mit SQLDataReader ) schrieb und der Code die bereits geschriebenen gespeicherten Legacy-Prozeduren aufrief . Es gibt Hunderte dieser alten gespeicherten Prozeduren, die einen Großteil der Geschäftslogik enthalten. Meine Datenzugriffsschicht musste eine Art strukturierter Daten an die C # -basierte Geschäftslogikschicht zurückgeben, um einige Manipulationen durchzuführen ( obwohl es fast keine gibt ). Jede gespeicherte Prozedur gibt einen anderen Datensatz zurück ( Tabellenspalten ). Anstatt Dutzende von Klassen oder Strukturen zu erstellen, um die zurückgegebenen Daten zu speichern und an die BLL zu übergeben, habe ich den folgenden Code geschrieben, der recht elegant und ordentlich aussieht.

public static dynamic GetSomeData(ParameterDTO dto)
        {
            dynamic result = null;
            string SPName = "a_legacy_stored_procedure";
            using (SqlConnection connection = new SqlConnection(DataConnection.ConnectionString))
            {
                SqlCommand command = new SqlCommand(SPName, connection);
                command.CommandType = System.Data.CommandType.StoredProcedure;                
                command.Parameters.Add(new SqlParameter("@empid", dto.EmpID));
                command.Parameters.Add(new SqlParameter("@deptid", dto.DeptID));
                connection.Open();
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        dynamic row = new ExpandoObject();
                        row.EmpName = reader["EmpFullName"].ToString();
                        row.DeptName = reader["DeptName"].ToString();
                        row.AnotherColumn = reader["AnotherColumn"].ToString();                        
                        result = row;
                    }
                }
            }
            return result;
        }
user1451111
quelle
0
  1. Sie können mit Pythonnet in dynamische Sprachen wie CPython aufrufen:

dynamic np = Py.Import("numpy")

  1. Sie können Generika umwandeln, dynamicwenn Sie numerische Operatoren auf sie anwenden. Dies bietet Typensicherheit und vermeidet Einschränkungen von Generika. Dies ist im Wesentlichen * Ententypisierung:

T y = x * (dynamic)x, wo typeof(x) is T

denfromufa
quelle
0

Ein weiterer Anwendungsfall für die dynamicEingabe sind virtuelle Methoden, bei denen ein Problem mit Kovarianz oder Kontravarianz auftritt. Ein solches Beispiel ist die berüchtigte CloneMethode, die ein Objekt des gleichen Typs wie das Objekt zurückgibt, für das es aufgerufen wird. Dieses Problem wird mit einer dynamischen Rückgabe nicht vollständig gelöst, da die statische Typprüfung umgangen wird. Zumindest müssen Sie bei der Verwendung von Plain nicht immer hässliche Casts verwenden object. Ansonsten werden die Casts implizit.

public class A
{
    // attributes and constructor here
    public virtual dynamic Clone()
    {
        var clone = new A();
        // Do more cloning stuff here
        return clone;
    }
}

public class B : A
{
    // more attributes and constructor here
    public override dynamic Clone()
    {
        var clone = new B();    
        // Do more cloning stuff here
        return clone;
    }
}    

public class Program
{
    public static void Main()
    {
        A a = new A().Clone();  // No cast needed here
        B b = new B().Clone();  // and here
        // do more stuff with a and b
    }
}
Frederic
quelle