Casting vs Konvertieren eines Objekts in String, wenn das Objekt wirklich eine Zeichenfolge ist

74

Dies ist nicht wirklich ein Problem, aber ich bin neugierig. Wenn ich eine Zeichenfolge in einer DataRow speichere, wird sie in Object umgewandelt. Wenn ich es verwenden möchte, muss ich es in ToString umwandeln. Soweit ich weiß, gibt es verschiedene Möglichkeiten, dies zu tun

string name = (string)DataRowObject["name"]; //valid since I know it's a string

und eine andere ist:

string name = DataRowObject["name"].ToString();

Mich interessiert, was ist der Unterschied zwischen beiden? Ist der erste effizienter? (Dies ist nur eine Spekulation, in meinem Kopf wird die ToString () -Methode durch einen Schleifenmechanismus implementiert, bei dem das Casting "schneller" sein könnte, dies ist jedoch nur ein "Bauchgefühl", das ich habe).

Gibt es dafür noch eine schnellere / elegantere Möglichkeit?

Kann jemand das für mich klären?

David Božjak
quelle
4
Ich weiß, dass Sie erwähnt haben, dass das Objekt eine Zeichenfolge ist, aber falls Sie nicht sicher sind, ob das zurückgegebene Objekt null ist, können Sie es auch mit "Convert.ToString (DataRowObject [" name "]);" Dies hat den zusätzlichen Vorteil, dass eine leere Zeichenfolge (string.empty) zurückgegeben wird, wenn das Objekt null ist, um Nullreferenzausnahmen zu vermeiden.
n00b

Antworten:

54

Die beiden sind für unterschiedliche Zwecke gedacht. Die ToString-Methode eines Objekts soll eine Zeichenfolgendarstellung dieses Objekts zurückgeben. Das Casting ist ganz anders, und das Schlüsselwort 'as' führt, wie gesagt, eine bedingte Besetzung durch. Das Schlüsselwort 'as' lautet im Wesentlichen "Holen Sie sich eine Referenz dieses Typs auf dieses Objekt, wenn dieses Objekt von diesem Typ ist", während ToString "Holen Sie mir eine Zeichenfolgendarstellung dieses Objekts" sagt. Das Ergebnis mag in einigen Fällen das gleiche sein, aber die beiden sollten niemals als austauschbar angesehen werden, da sie, wie gesagt, für unterschiedliche Zwecke existieren. Wenn Sie eine Besetzung beabsichtigen, sollten Sie immer eine Besetzung verwenden, NICHT ToString.

von http://www.codeguru.com/forum/showthread.php?t=443873

Siehe auch http://bytes.com/groups/net-c/225365-tostring-string-cast

Adriaan Stander
quelle
Also, wenn ich das richtig verstehe. .ToString gibt immer eine Zeichenfolge des Objekts zurück. Während des Castings schlägt fehl, wenn es nicht als String zurückgegeben werden kann?
DaImTo
1
@DaImTo: Wenn Sie ein Objekt vom Typ A in Typ B umwandeln (wenn das Casting erfolgreich ist), haben Sie ein neues Objekt, das Sie wieder in den Typ A umwandeln können. Casting ist nicht zu ändern, wer sie sind (der Kern), sondern zu ändern, wie sie aussehen werden. Das Konvertieren ist in den meisten Fällen ein One-Way-Ticket. Es wird ein neues Objekt (nur) für das alte Objekt dargestellt. Beispiel: Ein Schülerobjekt st bei der Konvertierung in String () ist eine Zeichenfolge, die wie Schüler aussieht: @ 1343; 43234. Glaubst du, du kannst es wieder in einen Schüler verwandeln, der einen Feldwert hat?
Andiana
@Andiana Im Ref Exam Book für c # heißt es: "Wenn Sie Ihre eigenen Typen erstellen, können Sie ToString überschreiben, um eine Zeichenfolgendarstellung Ihres Objekts zurückzugeben. Bei Bedarf können Sie eine Parse- und TryParse-Methode erstellen, die die Zeichenfolge wieder in das Original konvertiert." Die Implementierung der IFormattable-Schnittstelle ist erforderlich, damit Ihr Objekt von der Convert-Klasse verwendet werden kann. " Könnten Sie es im Lichte dessen erklären, was Sie zuvor gesagt haben? Vielen Dank
Ashraf Alshahawy
Würde string name = DataRowObject ["name"] als String; Arbeit ? Nur neugierig ...
Jack Griffin
30

Wenn Sie wissen, dass es ein ist, Stringdann werfen Sie es auf jeden Fall zu einem String. Das Casting Ihres Objekts ist schneller als das Aufrufen einer virtuellen Methode.

Bearbeiten: Hier sind die Ergebnisse einiger Benchmarking:

============ Casting vs. virtual method ============
cast 29.884 1.00
tos  33.734 1.13

Ich habe Jon Skeet BenchmarkHelperso benutzt:

using System;
using BenchmarkHelper;

class Program
{
    static void Main()
    {
        Object input = "Foo";
        String output = "Foo";

        var results 
           = TestSuite.Create("Casting vs. virtual method", input, output)
            .Add(cast)
            .Add(tos)
            .RunTests()
            .ScaleByBest(ScalingMode.VaryDuration);

        results.Display(ResultColumns.NameAndDuration | ResultColumns.Score,
                results.FindBest());
    }

    static String cast(Object o)
    {
        return (String)o;
    }

    static String tos(Object o)
    {
        return o.ToString();
    }
}

Es scheint also, dass das Casting tatsächlich etwas schneller ist als das Anrufen ToString().

Andrew Hare
quelle
1
@ Andrew: Hast du das verglichen? Es mag sich geändert haben, aber als ich es das letzte Mal verglichen habe, stellte ich fest, dass die virtuelle Methode tatsächlich schneller war. Ich habe es nicht erwartet, aber es war.
Jon Skeet
@ Jon - Nein, habe ich nicht! Ich muss das überprüfen, um sicherzugehen.
Andrew Hare
1
@ AndrewHare- Jons Link führt zu einem 505
TheGeekZn
16

Grundsätzlich ist es in Ihrem Fall besser, die Typumwandlung zu belassen, da .ToString () Fehler verbergen kann. Beispielsweise wurde Ihr Datenbankschema geändert und der Name ist nicht mehr vom Typ Zeichenfolge, aber mit .ToString () funktioniert Ihr Code weiterhin. In diesem Fall ist es daher besser, Typguss zu verwenden.

Hier ist die Implementierung von String.ToString () - nichts Besonderes =)

public override string ToString()
{
    return this;
}
Dzmitry Huba
quelle
5

Downcasting ist eine relativ langsame Operation, da CLR verschiedene Laufzeit-Typprüfungen durchführen muss. Doch in diesem speziellen Szenario Gießen stringbesser geeignet ist als Aufruf ToString()aus Gründen der Konsistenz (man kann nicht rufen ToInt32auf object, sondern warf es auf int) und maintanability.

Anton Gogolev
quelle
Es ist vielleicht nicht so langsam wie Sie denken - bitte sehen Sie meine Antwort.
Andrew Hare
5

Ich möchte noch einen Kommentar abgeben

Wenn Sie Casting verwenden möchten: string name = (string) DataRowObject ["name"], erhalten Sie eine Ausnahme: Objekt vom Typ 'System.DBNull' kann nicht in 'System.String' umgewandelt werden, falls der Datensatz in Die Datenbanktabelle hat den Wert Null.

In diesem Szenario müssen Sie Folgendes verwenden: string name = DataRowObject ["name"]. ToString () oder

Sie müssen nach Nullwerten wie suchen

if(!string.IsNullOrEmpty(DataRowObject["name"].ToString()))
{
string name = (string)DataRowObject["name"];
}
else
{
//i.e Write error to the log file
string error = "The database table has a null value";

}
VladL
quelle
3

Für Datenobjekte empfehle ich Ihnen, das Schlüsselwort "as" wie den folgenden Code zu verwenden.

string name = DataRowObject["name"] as string;

Bitte überprüfen Sie dies, bevor Sie den Wert verwenden.

if(name != null)
{
    // statement for empty string or it has value
}
else
{
    // statement for no data in this object.    
}
Seelen Meister
quelle
string name = (row["name"] as string) ?? "default";
Wäre
2

In diesem Fall:

string name = DataRowObject["name"].ToString();

da es ein ist string, denke ich, dass die ToString()Methode eines String-Objekts einfach ist wie:

return this;

IMHO gibt es also keine Leistungseinbußen.

PS Ich bin ein Java-Programmierer, daher ist diese Antwort nur eine Vermutung.

dfa
quelle
Ich denke, DataRowObject kennt keine Typen und speichert alles als Objekte, daher ist es definitiv nicht so einfach, dies zurückzugeben.
martijn_himself
3
@martjin_himself Willkommen in der Welt der Objektorientierung, ich möchte Ihnen einen neuen Freund vorstellen: Polymorphismus.
Fortan
@fortran würde es Ihnen etwas ausmachen, näher darauf einzugehen? Mir ist bewusst, dass alles ein Objekt ist und der Polymorphismus es Ihnen ermöglicht, eine Zeichenfolge so zu behandeln, als wäre es ein Objekt. Dies ist hier jedoch irrelevant, es sei denn, mir fehlt etwas? prost
martijn_himself
@dfa Entschuldigung, was ich sagen wollte ist, dass es nicht als String gespeichert ist. Ich wünschte, ich könnte Kommentare bearbeiten, wenn sie etwas hart klingen :)
martijn_himself
1

ToString () führt standardmäßig keine Umwandlung durch. Der Zweck besteht darin, eine Zeichenfolge zurückzugeben, die den Typ darstellt (z. B. "System.Object").

Wenn Sie Casting vermeiden möchten, können Sie versuchen, sich eine Implementierung vorzustellen, die stark typisiert ist (z. B. mithilfe von Generika) und DataRowObject insgesamt vermeidet.

martijn_himself
quelle
1

Ich weiß, dass Sie erwähnt haben, dass das Objekt eine Zeichenfolge ist, aber falls Sie befürchten, dass das zurückgegebene Objekt null ist, können Sie es auch mit "Convert.ToString (DataRowObject [" name "]);" Dies hat den zusätzlichen Vorteil, dass eine leere Zeichenfolge (string.empty) zurückgegeben wird, wenn das Objekt null ist, um Nullreferenzausnahmen zu vermeiden (es sei denn, Sie möchten in solchen Fällen natürlich eine Ausnahme auslösen).

n00b
quelle
Die Verwendung von "Convert.ToString" bietet einen zusätzlichen Vorteil: Sie können einen Nullwert übergeben, ohne dass eine Ausnahme ausgelöst wird. Link
Remy