Typprüfung: typeof, GetType oder is?


1512

Ich habe viele Leute gesehen, die den folgenden Code verwenden:

Type t = typeof(obj1);
if (t == typeof(int))
    // Some code here

Aber ich weiß, dass Sie das auch tun können:

if (obj1.GetType() == typeof(int))
    // Some code here

Oder dieses:

if (obj1 is int)
    // Some code here

Persönlich denke ich, dass der letzte der sauberste ist, aber fehlt mir etwas? Welches ist das beste oder ist es eine persönliche Präferenz?


28
Vergiss nicht as!
RCIX

82
asist aber nicht wirklich Typprüfung ...
Jason

49
asist sicherlich eine Form der Typprüfung, genauso wie es isist! Es wird effektiv ishinter den Kulissen verwendet und überall in MSDN an Orten verwendet, an denen es die Code-Sauberkeit im Vergleich zu verbessert is. Anstatt zuerst nachzuschlagen is, wird durch einen Aufruf aseine gebrauchsfertige typisierte Variable erstellt: Wenn sie null ist, antworten Sie entsprechend. Andernfalls fahren Sie fort. Sicherlich etwas, das ich gesehen und ziemlich oft benutzt habe.
Zaccone

15
Es gibt einen signifikanten Leistungsunterschied zugunsten von as/ is(behandelt in stackoverflow.com/a/27813381/477420 ), vorausgesetzt, die semantische Funktion für Ihren Fall.
Alexei Levenkov

@samusarin es "verwendet" keine Reflexion. Die GetTypeMethode, auf die Sie verlinken, ist in System.Reflection.Assembly- eine völlig andere Methode und hier irrelevant.
Kirk Woll

Antworten:


1848

Alle sind unterschiedlich.

  • typeof Nimmt einen Typnamen (den Sie zur Kompilierungszeit angeben).
  • GetType Ruft den Laufzeittyp einer Instanz ab.
  • is Gibt true zurück, wenn sich eine Instanz im Vererbungsbaum befindet.

Beispiel

class Animal { } 
class Dog : Animal { }

void PrintTypes(Animal a) { 
    Console.WriteLine(a.GetType() == typeof(Animal)); // false 
    Console.WriteLine(a is Animal);                   // true 
    Console.WriteLine(a.GetType() == typeof(Dog));    // true
    Console.WriteLine(a is Dog);                      // true 
}

Dog spot = new Dog(); 
PrintTypes(spot);

Was ist mit typeof(T)? Wird es auch beim Kompilieren behoben?

Ja. T ist immer der Typ des Ausdrucks. Denken Sie daran, dass eine generische Methode im Grunde eine ganze Reihe von Methoden mit dem entsprechenden Typ ist. Beispiel:

string Foo<T>(T parameter) { return typeof(T).Name; }

Animal probably_a_dog = new Dog();
Dog    definitely_a_dog = new Dog();

Foo(probably_a_dog); // this calls Foo<Animal> and returns "Animal"
Foo<Animal>(probably_a_dog); // this is exactly the same as above
Foo<Dog>(probably_a_dog); // !!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal.

Foo(definitely_a_dog); // this calls Foo<Dog> and returns "Dog"
Foo<Dog>(definitely_a_dog); // this is exactly the same as above.
Foo<Animal>(definitely_a_dog); // this calls Foo<Animal> and returns "Animal". 
Foo((Animal)definitely_a_dog); // this does the same as above, returns "Animal"

29
Ah, wenn ich also eine Ford-Klasse habe, die von Car und einer Instanz von Ford abgeleitet ist, ist es wahr, wenn in dieser Instanz "is Car" aktiviert ist. Macht Sinn!
Jason

2
Zur Verdeutlichung war mir das bewusst, aber ich habe es kommentiert, bevor Sie ein Codebeispiel hinzugefügt haben. Ich wollte versuchen, Ihrer bereits ausgezeichneten Antwort eine klare englische Klarheit zu verleihen.
Jason

12
@Shimmy Wenn typeof zur Kompilierungszeit ausgewertet wird und GetType () zur Laufzeit ausgewertet wird, ist es sinnvoll, dass GetType () einen leichten Leistungseinbruch erleidet
Cedric Mamo

Was ist mit neuem Hund ()? GetType () ist Tier oder Typ von (Hund) ist Tier, es gibt nur eine Warnung und keinen Fehler?
Prerak K

7
@PrerakK new Dog().GetType() is Animalgibt false zurück (und auch Ihre andere Version), da .GetType()ein Objekt vom Typ zurückgegeben Typewird und Typekein Objekt ist Animal.
Maarten

195

Verwenden typeofSie diese Option, wenn Sie den Typ zur Kompilierungszeit abrufen möchten . Verwenden GetTypeSie diese Option, wenn Sie den Typ zur Ausführungszeit abrufen möchten . Es gibt selten Fälle, die verwendet werden müssen, isda es sich um eine Umwandlung handelt, und in den meisten Fällen wird die Variable trotzdem umgewandelt.

Es gibt eine vierte Option, die Sie nicht in Betracht gezogen haben (insbesondere, wenn Sie ein Objekt in den Typ umwandeln möchten, den Sie ebenfalls finden). das ist zu verwenden as.

Foo foo = obj as Foo;

if (foo != null)
    // your code here

Dies verwendet nur eine Besetzung, während dieser Ansatz:

if (obj is Foo)
    Foo foo = (Foo)obj;

erfordert zwei .

Update (Januar 2020):

  • Ab C # 7+ können Sie jetzt Inline-Casting durchführen, sodass der "Ist" -Ansatz jetzt auch in einem Cast ausgeführt werden kann.

Beispiel:

if(obj is Foo newLocalFoo)
{
    // For example, you can now reference 'newLocalFoo' in this local scope
    Console.WriteLine(newLocalFoo);
}

4
Führt mit den Änderungen in .NET 4 isnoch eine Besetzung durch?
Ahsteele

6
Ist diese Antwort richtig? Stimmt es, dass Sie eine Instanz wirklich an typeof () übergeben können? Meine Erfahrung war Nein. Aber ich denke, es ist im Allgemeinen richtig, dass das Überprüfen einer Instanz zur Laufzeit erfolgen muss, während das Überprüfen einer Klasse zur Kompilierungszeit möglich sein sollte.
Jon Coombs

4
@jon (4 Jahre nach Ihrem Q.), nein, Sie können keine Instanz übergeben typeof(), und diese Antwort schlägt nicht vor, dass Sie dies können. Sie übergeben stattdessen den Typ, dh typeof(string)funktioniert, typeof("foo")funktioniert nicht.
Abel

Ich glaube nicht, dass isdie Besetzung als solche ausgeführt wird, sondern eine besondere Operation in IL.
Abatishchev

3
Wir können jetzt tunif (obj is Foo foo) { /* use foo here */ }
Ivan García Topete

71

1.

Type t = typeof(obj1);
if (t == typeof(int))

Dies ist unzulässig, da typeofnur Typen und keine Variablen verwendet werden. Ich gehe davon aus, dass obj1 eine Variable ist. Auf diese Weise typeofist es also statisch und erledigt seine Arbeit zur Kompilierungszeit anstatt zur Laufzeit.

2.

if (obj1.GetType() == typeof(int))

Dies ist, truewenn obj1es genau vom Typ ist int. Wenn obj1abgeleitet von int, wird die if-Bedingung sein false.

3.

if (obj1 is int)

Dies ist, truewenn obj1es sich um eine inthandelt oder wenn es von einer aufgerufenen Klasse abgeleitet intist oder wenn eine aufgerufene Schnittstelle implementiert wird int.


Wenn Sie an 1 denken, haben Sie Recht. Und doch habe ich es hier in mehreren Codebeispielen gesehen. Es sollte Typ t = obj1.GetType () sein;
Jason

4
Ja, ich denke schon. "typeof (obj1)" wird nicht kompiliert, wenn ich es versuche.
Scott Langham

4
Es ist unmöglich, von System.Int32 oder einem anderen Werttyp in C #
abzuleiten

können Sie sagen, was wäre typeof (typeof (system.int32))
Sana

1
@Sana, warum versuchst du es nicht :) Ich würde mir vorstellen, dass du eine Instanz von System.Type zurück bekommst, die den Typ System.Type darstellt! Dokumentation für typeof ist hier: docs.microsoft.com/en-us/dotnet/csharp/language-reference/…
Scott Langham

53
Type t = typeof(obj1);
if (t == typeof(int))
    // Some code here

Dies ist ein Fehler. Der Operator typeof in C # kann nur Typnamen annehmen, keine Objekte.

if (obj1.GetType() == typeof(int))
    // Some code here

Dies wird funktionieren, aber vielleicht nicht so, wie Sie es erwarten würden. Wie Sie hier gezeigt haben, ist dies für Werttypen akzeptabel. Für Referenztypen wird jedoch nur true zurückgegeben, wenn der Typ genau derselbe Typ ist und nicht etwas anderes in der Vererbungshierarchie. Zum Beispiel:

class Animal{}
class Dog : Animal{}

static void Foo(){
    object o = new Dog();

    if(o.GetType() == typeof(Animal))
        Console.WriteLine("o is an animal");
    Console.WriteLine("o is something else");
}

Dies würde drucken "o is something else", weil die Art der oist Dog, nicht Animal. Sie können dies jedoch zum Laufen bringen, wenn Sie die IsAssignableFromMethode der TypeKlasse verwenden.

if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
    Console.WriteLine("o is an animal");

Diese Technik hinterlässt jedoch immer noch ein großes Problem. Wenn Ihre Variable null ist, GetType()löst der Aufruf von eine NullReferenceException aus. Damit es richtig funktioniert, müssen Sie Folgendes tun:

if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
    Console.WriteLine("o is an animal");

Damit haben Sie ein gleichwertiges Verhalten des isSchlüsselworts. Wenn dies das gewünschte Verhalten ist, sollten Sie daher das isSchlüsselwort verwenden, das lesbarer und effizienter ist.

if(o is Animal)
    Console.WriteLine("o is an animal");

In den meisten Fällen ist das isSchlüsselwort jedoch immer noch nicht das, was Sie wirklich wollen, da es normalerweise nicht ausreicht, nur zu wissen, dass ein Objekt von einem bestimmten Typ ist. Normalerweise wollen Sie tatsächlich nutzen das Objekt als Instanz dieses Typs, die es auch erfordert Gießen. Und so können Sie feststellen, dass Sie Code wie folgt schreiben:

if(o is Animal)
    ((Animal)o).Speak();

Dadurch überprüft die CLR den Objekttyp bis zu zweimal. Es wird einmal überprüft, um den isBediener zufrieden zu stellen , und wenn dies otatsächlich der AnimalFall ist, wird es erneut überprüft, um die Besetzung zu validieren.

Es ist effizienter, dies stattdessen zu tun:

Animal a = o as Animal;
if(a != null)
    a.Speak();

Der asOperator ist eine Besetzung, die keine Ausnahme auslöst, wenn sie fehlschlägt, sondern zurückkehrt null. Auf diese Weise überprüft die CLR den Objekttyp nur einmal, und danach müssen wir nur noch eine Nullprüfung durchführen, was effizienter ist.

Aber Vorsicht: Viele Menschen geraten mit in eine Falle as. Da es keine Ausnahmen gibt, betrachten einige Leute es als "sichere" Besetzung, und sie verwenden es ausschließlich und meiden reguläre Besetzungen. Dies führt zu solchen Fehlern:

(o as Animal).Speak();

In diesem Fall wird der Entwickler deutlich unter der Annahme , dass owird immer eine sein Animal, und solange ihre Annahme richtig ist, funktioniert alles einwandfrei. Aber wenn sie falsch liegen, dann ist das, was sie hier haben, ein NullReferenceException. Mit einer regulären Besetzung hätten sie InvalidCastExceptionstattdessen eine bekommen , die das Problem genauer identifiziert hätte.

Manchmal ist dieser Fehler schwer zu finden:

class Foo{
    readonly Animal animal;

    public Foo(object o){
        animal = o as Animal;
    }

    public void Interact(){
        animal.Speak();
    }
}

Dies ist ein weiterer Fall, in dem der Entwickler eindeutig erwartet o, dass dies Animaljedes Mal der Fall ist. Dies ist jedoch im Konstruktor, in dem die asBesetzung verwendet wird, nicht offensichtlich . Es ist nicht offensichtlich, bis Sie zu der InteractMethode gelangen, bei der animalerwartet wird, dass das Feld positiv zugewiesen wird. In diesem Fall kommt es nicht nur zu einer irreführenden Ausnahme, sondern sie wird erst viel später ausgelöst, als der eigentliche Fehler aufgetreten ist.

Zusammenfassend:

  • Wenn Sie nur wissen müssen, ob ein Objekt von einem Typ ist oder nicht, verwenden Sie is.

  • Wenn Sie ein Objekt als Instanz eines bestimmten Typs behandeln müssen, aber nicht sicher sind, ob das Objekt von diesem Typ ist, verwenden Sie es asund suchen Sie nach null.

  • Wenn Sie ein Objekt als Instanz eines bestimmten Typs behandeln müssen und das Objekt von diesem Typ sein soll, verwenden Sie eine reguläre Besetzung.


Was ist daran falsch, wenn (o ist Tier) ((Tier) o) .Speak (); ? Kannst du bitte mehr Details geben?
Batmaci

2
@ Batmaci: Es ist in der Antwort - es verursacht zwei Typprüfungen. Das erste Mal ist o is Animal, dass die CLR prüfen muss, ob der Typ der Variablen ein oist Animal. Das zweite Mal wird geprüft, wann die Anweisung eingefügt wird ((Animal)o).Speak(). Anstatt zweimal zu prüfen, überprüfen Sie einmal mit as.
Siride

Ich fand das eine absolut großartige Erklärung, danke für die Klarstellung!
Paul Efford

16

Wenn Sie C # 7 verwenden, ist es Zeit für ein Update von Andrew Hares großartiger Antwort. Der Mustervergleich hat eine nette Verknüpfung eingeführt, die uns eine typisierte Variable im Kontext der if-Anweisung gibt, ohne dass eine separate Deklaration / Besetzung und Prüfung erforderlich ist:

if (obj1 is int integerValue)
{
    integerValue++;
}

Für eine einzelne Besetzung wie diese sieht das ziemlich überwältigend aus, aber es scheint wirklich, wenn viele mögliche Typen in Ihre Routine kommen. Das Folgende ist der alte Weg, um zweimaliges Casting zu vermeiden:

Button button = obj1 as Button;
if (button != null)
{
    // do stuff...
    return;
}
TextBox text = obj1 as TextBox;
if (text != null)
{
    // do stuff...
    return;
}
Label label = obj1 as Label;
if (label != null)
{
    // do stuff...
    return;
}
// ... and so on

Es hat mich immer gestört, diesen Code so weit wie möglich zu verkleinern und doppelte Besetzungen desselben Objekts zu vermeiden. Das Obige ist gut komprimiert und weist folgende Muster auf:

switch (obj1)
{
    case Button button:
        // do stuff...
        break;
    case TextBox text:
        // do stuff...
        break;
    case Label label:
        // do stuff...
        break;
    // and so on...
}

BEARBEITEN: Die längere neue Methode wurde aktualisiert, um einen Schalter gemäß Palecs Kommentar zu verwenden.


1
Mit switchErklärung mit Mustervergleich ist in diesem Fall ratsam.
Palec

Wie würden Sie mit einem nicht umgehen? In diesem speziellen Codeblock? if (obj1 is int integerValue) { integerValue++; }
Ben Vertonghen

Ben, wenn ich Ihre Frage verstehe, hätte ich nur eine else-Anweisung, um andere Fälle zu behandeln, da Sie keine Ganzzahl in eine Ganzzahlvariable einfügen können. :)
JoelC

14

Ich hatte eine TypeEigenschaft zum Vergleichen und konnte sie nicht verwenden is(wie my_type is _BaseTypetoLookFor), aber ich konnte diese verwenden:

base_type.IsInstanceOfType(derived_object);
base_type.IsAssignableFrom(derived_type);
derived_type.IsSubClassOf(base_type);

Beachten Sie dies IsInstanceOfTypeund IsAssignableFromkehren Sie zurück, truewenn Sie dieselben Typen vergleichen, wobei IsSubClassOf zurückgibt false. Und IsSubclassOffunktioniert nicht an Schnittstellen, wo die anderen beiden tun. (Siehe auch diese Frage und Antwort .)

public class Animal {}
public interface ITrainable {}
public class Dog : Animal, ITrainable{}

Animal dog = new Dog();

typeof(Animal).IsInstanceOfType(dog);     // true
typeof(Dog).IsInstanceOfType(dog);        // true
typeof(ITrainable).IsInstanceOfType(dog); // true

typeof(Animal).IsAssignableFrom(dog.GetType());      // true
typeof(Dog).IsAssignableFrom(dog.GetType());         // true
typeof(ITrainable).IsAssignableFrom(dog.GetType()); // true

dog.GetType().IsSubclassOf(typeof(Animal));            // true
dog.GetType().IsSubclassOf(typeof(Dog));               // false
dog.GetType().IsSubclassOf(typeof(ITrainable)); // false

9

Ich bevorzuge ist

Das heißt, wenn Sie verwenden ist , sind Sie wahrscheinlich nicht Vererbung richtig verwenden.

Angenommen, diese Person: Entität und dieses Tier: Entität. Feed ist eine virtuelle Methode in Entity (um Neil glücklich zu machen)

class Person
{
  // A Person should be able to Feed
  // another Entity, but they way he feeds
  // each is different
  public override void Feed( Entity e )
  {
    if( e is Person )
    {
      // feed me
    }
    else if( e is Animal )
    {
      // ruff
    }
  }
}

Lieber

class Person
{
  public override void Feed( Person p )
  {
    // feed the person
  }
  public override void Feed( Animal a )
  {
    // feed the animal
  }
}

1
Ersteres würde ich niemals tun, wenn ich wüsste, dass die Person von Animal stammt.
Jason

3
Letzteres verwendet die Vererbung auch nicht wirklich. Foo sollte eine virtuelle Entitätsmethode sein, die in Person und Tier überschrieben wird.
Neil Williams

2
@ Bobobobo Ich denke du meinst "Überladung", nicht "Vererbung".
lc.

@lc: Nein, ich meine Vererbung. Das erste Beispiel ist eine Art falscher Weg (mit is ), um ein anderes Verhalten zu erhalten. Das zweite Beispiel verwendet die Überladung yes, vermeidet jedoch die Verwendung von is .
Bobobobo

1
Das Problem mit dem Beispiel ist, dass es nicht skaliert. Wenn Sie neue Entitäten hinzugefügt haben, die gegessen werden müssen (z. B. ein Insekt oder ein Monster), müssen Sie der Entitätsklasse eine neue Methode hinzufügen und diese dann in Unterklassen überschreiben, die sie füttern. Dies ist nicht vorzuziehen als eine Liste, wenn (Entität ist X), sonst wenn (Entität ist Y) ... Dies verstößt gegen LSP und OCP, Vererbung ist wahrscheinlich nicht die beste Lösung für das Problem. Eine Form der Delegation wäre wahrscheinlich vorzuziehen.
ebrown

5

Ich glaube, der letzte befasst sich auch mit der Vererbung (z. B. Hund ist Tier == wahr), was in den meisten Fällen besser ist.


2

Es kommt darauf an, was ich mache. Wenn ich einen Bool-Wert benötige (z. B. um festzustellen, ob ich in einen Int umwandle), verwende ich is. Wenn ich den Typ aus irgendeinem Grund tatsächlich brauche (z. B. um zu einer anderen Methode überzugehen), werde ich ihn verwenden GetType().


1
Guter Punkt. Ich habe vergessen zu erwähnen, dass ich zu dieser Frage gekommen bin, nachdem ich mir mehrere Antworten angesehen hatte, bei denen eine if-Anweisung zum Überprüfen eines Typs verwendet wurde.
Jason

0

Der letzte ist sauberer, offensichtlicher und sucht auch nach Subtypen. Die anderen prüfen nicht auf Polymorphismus.


0

Wird verwendet, um das System.Type-Objekt für einen Typ abzurufen. Ein Ausdruckstyp hat die folgende Form:

System.Type type = typeof(int);

Example:

    public class ExampleClass
    {
       public int sampleMember;
       public void SampleMethod() {}

       static void Main()
       {
          Type t = typeof(ExampleClass);
          // Alternatively, you could use
          // ExampleClass obj = new ExampleClass();
          // Type t = obj.GetType();

          Console.WriteLine("Methods:");
          System.Reflection.MethodInfo[] methodInfo = t.GetMethods();

          foreach (System.Reflection.MethodInfo mInfo in methodInfo)
             Console.WriteLine(mInfo.ToString());

          Console.WriteLine("Members:");
          System.Reflection.MemberInfo[] memberInfo = t.GetMembers();

          foreach (System.Reflection.MemberInfo mInfo in memberInfo)
             Console.WriteLine(mInfo.ToString());
       }
    }
    /*
     Output:
        Methods:
        Void SampleMethod()
        System.String ToString()
        Boolean Equals(System.Object)
        Int32 GetHashCode()
        System.Type GetType()
        Members:
        Void SampleMethod()
        System.String ToString()
        Boolean Equals(System.Object)
        Int32 GetHashCode()
        System.Type GetType()
        Void .ctor()
        Int32 sampleMember
    */

In diesem Beispiel wird mithilfe der GetType-Methode der Typ ermittelt, der das Ergebnis einer numerischen Berechnung enthält. Dies hängt von den Speicheranforderungen der resultierenden Anzahl ab.

    class GetTypeTest
    {
        static void Main()
        {
            int radius = 3;
            Console.WriteLine("Area = {0}", radius * radius * Math.PI);
            Console.WriteLine("The type is {0}",
                              (radius * radius * Math.PI).GetType()
            );
        }
    }
    /*
    Output:
    Area = 28.2743338823081
    The type is System.Double
    */

-4
if (c is UserControl) c.Enabled = enable;

4
Bitte bearbeiten Sie mit weiteren Informationen. Nur-Code- und "Versuch dies" -Antworten werden nicht empfohlen, da sie keinen durchsuchbaren Inhalt enthalten und nicht erklären, warum jemand "dies versuchen" sollte.
Abarisone

Ihre Antwort hat nichts mit der Frage zu tun.
Menxin

-5

Sie können den Operator "typeof ()" in C # verwenden, müssen jedoch den Namespace mit System.IO aufrufen. Sie müssen das Schlüsselwort "is" verwenden, wenn Sie nach einem Typ suchen möchten.


7
typeofist nicht in einem Namespace definiert, sondern ein Schlüsselwort. System.IOhat damit nichts zu tun.
Arturo Torres Sánchez

-5

Leistungstest typeof () vs GetType ():

using System;
namespace ConsoleApplication1
    {
    class Program
    {
        enum TestEnum { E1, E2, E3 }
        static void Main(string[] args)
        {
            {
                var start = DateTime.UtcNow;
                for (var i = 0; i < 1000000000; i++)
                    Test1(TestEnum.E2);
                Console.WriteLine(DateTime.UtcNow - start);
            }
            {
                var start = DateTime.UtcNow;
                for (var i = 0; i < 1000000000; i++)
                    Test2(TestEnum.E2);
                Console.WriteLine(DateTime.UtcNow - start);
            }
            Console.ReadLine();
        }
        static Type Test1<T>(T value) => typeof(T);
        static Type Test2(object value) => value.GetType();
    }
}

Ergebnisse im Debug-Modus:

00:00:08.4096636
00:00:10.8570657

Ergebnisse im Release-Modus:

00:00:02.3799048
00:00:07.1797128

1
DateTime.UtcNow sollte nicht für Leistungsmessungen verwendet werden. Mit Ihrem Code, aber mit der Stoppuhr-Klasse habe ich für den Debug-Modus anhaltend entgegengesetzte Ergebnisse erhalten. UseTypeOf: 00: 00: 14.5074469 UseGetType: 00: 00: 10.5799534. Der Release-Modus ist der gleiche wie erwartet
Alexey Shcherbak

@AlexeyShcherbak Der Unterschied zwischen Stoppuhr und DateTime.Now darf nicht länger als 10-20 ms sein. Überprüfen Sie Ihren Code erneut. Und Millisekunden interessieren mich in meinem Test nicht. Außerdem wird mein Code mit Stoppuhr mehrere Codezeilen länger sein.
Alexander Vasilyev

1
Es ist im Allgemeinen eine schlechte Praxis, nicht in Ihrem speziellen Fall.
Alexey Shcherbak

4
@AlexanderVasilyev Die Anzahl der Codezeilen sollte niemals als Argument verwendet werden, um etwas dokumentarisch Irreführendes zu tun . Wie in msdn.microsoft.com/en-us/library/system.datetime(v=vs.110).aspx zu sehen ist , DateTimesollte es nicht verwendet werden, wenn Sie sich Sorgen über Zeiten unter 100 ms machen , da es den Zeitrahmen des Betriebssystems verwendet. Im Vergleich zu Stopwatch, der die Prozessoren Tickverwendet, DateTimebeträgt die von a in Win7 verwendete Auflösung 15 ms.
Eric Wu
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.