การตรวจสอบประเภท: typeof, GetType หรือคืออะไร


1512

ฉันเคยเห็นหลายคนใช้รหัสต่อไปนี้:

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

แต่ฉันรู้ว่าคุณสามารถทำได้เช่นกัน:

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

หรือสิ่งนี้:

if (obj1 is int)
    // Some code here

โดยส่วนตัวแล้วฉันรู้สึกว่าอันสุดท้ายนั้นสะอาดที่สุด แต่มีบางอย่างที่ฉันขาดหายไปหรือไม่? อันไหนดีที่สุดที่จะใช้หรือมันเป็นการตั้งค่าส่วนตัว?


28
อย่าลืมas!
RCIX

82
asไม่ได้ตรวจสอบประเภทจริง ๆ ...
jasonh

49
asแน่นอนว่าเป็นรูปแบบของการตรวจสอบทุกชนิดมากเท่าที่เป็นisอยู่! มันมีประสิทธิภาพใช้isอยู่เบื้องหลังและมีการใช้ทั่วทุกสถานที่ใน MSDN isในสถานที่ที่จะช่วยเพิ่มรหัสความสะอาดเมื่อเทียบกับ แทนที่จะตรวจสอบisก่อนการเรียกเพื่อasสร้างตัวแปรที่พิมพ์ซึ่งพร้อมใช้งาน: หากเป็นโมฆะให้ตอบกลับอย่างเหมาะสม มิฉะนั้นดำเนินการต่อ บางสิ่งบางอย่างแน่นอนฉันได้เห็นและใช้งานไม่น้อย
Zaccone

15
มีความแตกต่างด้านประสิทธิภาพที่สำคัญในความโปรดปรานของas/ is(ครอบคลุมในstackoverflow.com/a/27813381/477420 ) สมมติว่าใช้ความหมายของมันสำหรับกรณีของคุณ
Alexei Levenkov

@samusarin มันไม่ได้สะท้อน "ใช้" GetTypeวิธีคุณเชื่อมโยงไปอยู่ในSystem.Reflection.Assembly- วิธีการที่แตกต่างกันอย่างสมบูรณ์และไม่เกี่ยวข้องที่นี่
Kirk Woll

คำตอบ:


1848

ทั้งหมดนั้นแตกต่างกัน

  • typeof ใช้ชื่อประเภท (ซึ่งคุณระบุ ณ เวลารวบรวม)
  • GetType รับประเภท runtime ของตัวอย่าง
  • is ผลตอบแทนจริงถ้าอินสแตนซ์ที่อยู่ในต้นไม้ที่สืบทอด

ตัวอย่าง

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);

เกี่ยวกับtypeof(T)อะไร มันยังแก้ไขในเวลารวบรวม?

ใช่. T เป็นนิพจน์ประเภทใดเสมอ โปรดจำไว้ว่าวิธีการทั่วไปนั้นเป็นวิธีการทั้งหมดที่มีประเภทที่เหมาะสม ตัวอย่าง:

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
อ๊ะถ้าฉันมีคลาสฟอร์ดที่มาจากรถยนต์และตัวอย่างของฟอร์ดการตรวจสอบว่า "เป็นรถยนต์" ในกรณีนั้นจะเป็นจริง มีเหตุผล!
jasonh

2
เพื่อชี้แจงฉันรู้ว่า แต่ฉันแสดงความคิดเห็นก่อนที่คุณจะเพิ่มตัวอย่างรหัส ฉันต้องการลองเพิ่มความชัดเจนภาษาอังกฤษธรรมดา ๆ ให้กับคำตอบที่ยอดเยี่ยมของคุณ
jasonh

12
@Shimmy ถ้า typeof ได้รับการประเมิน ณ เวลารวบรวมและ GetType () ได้รับการประเมิน ณ รันไทม์จากนั้นจะทำให้รู้สึกว่า GetType () ได้รับผลการปฏิบัติงานเล็กน้อย
Cedric Mamo

แล้วสุนัขใหม่ () GetType () คือสัตว์หรือประเภทของสุนัข (สุนัข) เป็นสัตว์มันแค่เตือนและไม่ผิดพลาด
Prerak K

7
@PrerakK new Dog().GetType() is Animalกลับเท็จ (และอื่น ๆ รุ่นเช่นกัน) เนื่องจาก.GetType()ผลตอบแทนที่วัตถุของการพิมพ์Typeและไม่ได้เป็นType Animal
Maarten

195

ใช้typeofเมื่อคุณต้องการที่จะได้รับชนิดที่เวลารวบรวม ใช้GetTypeเมื่อคุณต้องการที่จะได้รับชนิดที่เวลาดำเนินการ ไม่ค่อยมีกรณีใด ๆ ที่จะใช้isเช่นเดียวกับที่นักแสดงและในกรณีส่วนใหญ่คุณท้ายหล่อตัวแปรอยู่แล้ว

มีตัวเลือกที่สี่ที่คุณไม่ได้พิจารณา (โดยเฉพาะถ้าคุณจะส่งวัตถุชนิดที่คุณค้นหาด้วย); asที่มีการใช้งาน

Foo foo = obj as Foo;

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

นี้ใช้เพียงหนึ่งในนักแสดงในขณะที่วิธีการนี้:

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

ต้องใช้สอง

อัปเดต (ม.ค. 2020):

  • ตั้งแต่ C # 7+ตอนนี้คุณสามารถร่ายไลน์ได้ดังนั้นวิธี 'is' จึงสามารถทำได้ในการร่ายครั้งเดียวเช่นกัน

ตัวอย่าง:

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

4
ด้วยการเปลี่ยนแปลงใน. NET 4 isยังคงส่งนักแสดงหรือไม่
ahsteele

6
คำตอบนี้ถูกต้องหรือไม่ เป็นความจริงหรือไม่ที่คุณสามารถส่งต่ออินสแตนซ์ไปเป็น typeof () ได้ ประสบการณ์ของฉันไม่เคยมีมาก่อน แต่ฉันคิดว่าโดยทั่วไปแล้วการตรวจสอบอินสแตนซ์อาจต้องเกิดขึ้นขณะใช้งานจริงในขณะที่การตรวจสอบคลาสควรทำได้ในเวลารวบรวม
Jon Coombs

4
@jon (4 ปีหลังจากคิวของคุณ) ไม่คุณไม่สามารถผ่านตัวอย่างtypeof()และคำตอบนี้ไม่แนะนำให้คุณทำได้ คุณผ่านประเภทแทนเช่นใช้typeof(string)งานtypeof("foo")ไม่ได้
อาเบล

ฉันไม่เชื่อว่าisการแสดงจะเป็นเช่นนี้ แต่เป็นการปฏิบัติการพิเศษใน IL
abatishchev

3
ตอนนี้เราสามารถทำได้if (obj is Foo foo) { /* use foo here */ }
Ivan García Topete

71

1

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

สิ่งนี้เป็นสิ่งผิดกฎหมายเพราะtypeofใช้ได้กับชนิดเท่านั้นไม่ใช่ในตัวแปร ฉันถือว่า obj1 เป็นตัวแปร ดังนั้นด้วยวิธีนี้typeofเป็นแบบสแตติกและทำงานในเวลาคอมไพล์แทนรันไทม์

2

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

นี่คือtrueถ้าเป็นตรงประเภทobj1 intถ้าobj1มาจากที่ถ้าเงื่อนไขจะเป็นintfalse

3

if (obj1 is int)

นี่คือtrueถ้าobj1เป็นintหรือถ้ามันเกิดขึ้นจากระดับที่เรียกว่าหรือถ้ามันดำเนินการติดต่อที่เรียกว่าintint


คิดเกี่ยวกับ 1 คุณพูดถูก ถึงกระนั้นฉันก็เห็นมันในตัวอย่างโค้ดหลาย ๆ อันที่นี่ ควรเป็น Type t = obj1.GetType ();
jasonh

4
ใช่ฉันคิดอย่างนั้น "typeof (obj1)" ไม่รวบรวมเมื่อฉันลอง
Scott Langham

4
เป็นไปไม่ได้ที่จะได้รับมาจาก System.Int32 หรือประเภทค่าอื่น ๆ ใน C #
reggaeguitar

คุณสามารถบอกได้ว่าจะเป็น typeof (typeof (system.int32))
Sana

1
@Sana ทำไมคุณไม่ลองดู :) ฉันจะจินตนาการถึงแม้ว่าคุณจะได้รับอินสแตนซ์ของ System.Type ที่แสดงประเภท System.Type! เอกสารสำหรับ typeof อยู่ที่นี่: docs.microsoft.com/en-us/dotnet/csharp/language-reference/ ......
Scott Langham

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

นี่เป็นข้อผิดพลาด ตัวดำเนินการ typeof ใน C # สามารถใช้ชื่อประเภทได้เท่านั้นไม่ใช่วัตถุ

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

สิ่งนี้จะได้ผล แต่อาจไม่เป็นอย่างที่คุณคาดหวัง สำหรับประเภทค่าตามที่คุณแสดงไว้ที่นี่เป็นที่ยอมรับ แต่สำหรับประเภทอ้างอิงมันจะคืนค่าจริงถ้าประเภทนั้นเป็นประเภทเดียวกันแน่นอนไม่ใช่อย่างอื่นในลำดับชั้นการสืบทอด ตัวอย่างเช่น

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");
}

นี้จะพิมพ์"o is something else"เพราะประเภทของการoเป็นไม่ได้Dog Animalคุณสามารถใช้งานได้อย่างไรก็ตามหากคุณใช้IsAssignableFromวิธีการTypeเรียน

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

เทคนิคนี้ยังคงเป็นปัญหาสำคัญอยู่ ถ้าตัวแปรของคุณเป็นโมฆะการเรียกไปGetType()จะส่ง NullReferenceException ดังนั้นเพื่อให้ทำงานได้อย่างถูกต้องคุณต้อง:

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

ด้วยสิ่งนี้คุณมีพฤติกรรมที่เท่าเทียมกันของisคำหลัก ดังนั้นหากนี่เป็นพฤติกรรมที่คุณต้องการคุณควรใช้isคำหลักที่อ่านได้ง่ายและมีประสิทธิภาพมากขึ้น

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

ในกรณีส่วนใหญ่isคำหลักนั้นยังคงไม่ใช่สิ่งที่คุณต้องการเพราะปกติแล้วมันจะไม่เพียงพอที่จะรู้ว่าวัตถุนั้นเป็นประเภทใด โดยปกติแล้วคุณต้องการใช้วัตถุนั้นเป็นอินสแตนซ์ของประเภทนั้นซึ่งต้องใช้การคัดเลือกวัตถุด้วย ดังนั้นคุณอาจพบว่าคุณเขียนโค้ดเช่นนี้:

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

แต่นั่นทำให้ CLR ตรวจสอบประเภทของวัตถุได้ถึงสองครั้ง มันจะตรวจสอบอีกครั้งเพื่อตอบสนองisผู้ใช้งานและหากoเป็นจริงAnimalเราจะทำการตรวจสอบอีกครั้งเพื่อตรวจสอบการหล่อ

การทำเช่นนี้มีประสิทธิภาพมากกว่าแทน:

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

ผู้ประกอบการเป็นนักแสดงที่จะไม่โยนยกเว้นถ้ามันล้มเหลวแทนที่จะกลับas nullด้วยวิธีนี้ CLR จะตรวจสอบประเภทของวัตถุเพียงครั้งเดียวและหลังจากนั้นเราต้องทำการตรวจสอบแบบ null ซึ่งมีประสิทธิภาพมากขึ้น

แต่ระวัง: asหลายคนตกอยู่ในกับดักด้วย เพราะมันไม่ได้ส่งข้อยกเว้นบางคนคิดว่ามันเป็นนักแสดงที่ "ปลอดภัย" และพวกเขาใช้มันเป็นแบบปกติ สิ่งนี้นำไปสู่ข้อผิดพลาดเช่นนี้:

(o as Animal).Speak();

ในกรณีนี้ผู้พัฒนาคาดว่าoจะเป็นเสมอAnimalและตราบใดที่ข้อสันนิษฐานของพวกเขาถูกต้องทุกอย่างก็ใช้ได้ดี NullReferenceExceptionแต่ถ้าพวกเขากำลังที่ไม่ถูกต้องแล้วสิ่งที่พวกเขาจบลงด้วยการที่นี่เป็น ด้วยการร่ายปกติพวกเขาจะได้รับการInvalidCastExceptionแทนที่ซึ่งจะระบุปัญหาได้อย่างถูกต้องมากขึ้น

บางครั้งข้อผิดพลาดนี้อาจหายาก:

class Foo{
    readonly Animal animal;

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

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

นี่เป็นอีกกรณีหนึ่งที่ผู้พัฒนาคาดว่าoจะชัดเจนAnimalทุกครั้ง แต่นี่ไม่ชัดเจนในตัวสร้างที่asนักแสดงใช้ ไม่ชัดเจนจนกว่าคุณจะไปถึงInteractวิธีที่animalคาดว่าจะได้รับการกำหนดเขตบวก ในกรณีนี้ไม่เพียง แต่คุณจะจบลงด้วยข้อยกเว้นที่ทำให้เข้าใจผิด แต่จะไม่ถูกโยนทิ้งจนกว่าจะเกิดข้อผิดพลาดที่เกิดขึ้นจริง

สรุป:

  • หากคุณจำเป็นต้องรู้ว่าวัตถุมีประเภทให้ใช้isหรือไม่

  • หากคุณต้องการที่จะรักษาวัตถุเป็นตัวอย่างของบางประเภท แต่คุณไม่ทราบว่าวัตถุจะเป็นประเภทที่ใช้และตรวจสอบasnull

  • หากคุณต้องการปฏิบัติต่อวัตถุเป็นตัวอย่างของบางประเภทและวัตถุนั้นควรจะเป็นประเภทนั้นให้ใช้การร่ายปกติ


เกิดอะไรขึ้นกับสิ่งนี้ถ้า (o คือสัตว์) ((สัตว์) o). พูด (); ? คุณช่วยให้รายละเอียดเพิ่มเติมหน่อยได้ไหม?
batmaci

2
@batmaci: มันอยู่ในคำตอบ - มันทำให้เกิดการตรวจสอบสองประเภท ครั้งแรกที่เป็นo is Animalที่ต้องใช้ CLR เพื่อตรวจสอบว่าประเภทของตัวแปรเป็นo ครั้งที่สองมันจะตรวจสอบคือเมื่อมันได้ปลดเปลื้องในงบAnimal แทนที่จะตรวจสอบครั้งที่สองตรวจสอบครั้งเดียวโดยใช้((Animal)o).Speak() as
siride

ฉันพบว่านี่เป็นคำอธิบายที่ดีมากขอบคุณสำหรับการชี้แจง!
เปาโลเอฟฟอร์ด

16

หากคุณใช้ C # 7 แสดงว่าถึงเวลาแล้วสำหรับการอัพเดทคำตอบที่ยอดเยี่ยมของ Andrew Hare การจับคู่รูปแบบได้แนะนำทางลัดที่ดีซึ่งทำให้เรามีตัวแปรที่พิมพ์ภายในบริบทของคำสั่ง if โดยไม่ต้องมีการประกาศ / ส่งและการตรวจสอบที่แยกต่างหาก:

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

เรื่องนี้ดูไม่น่าสนใจเลยสำหรับนักแสดงเดี่ยวแบบนี้ แต่จริงๆแล้วมันจะส่องแสงเมื่อคุณมีหลาย ๆ ประเภทที่เป็นไปได้ ด้านล่างเป็นวิธีเก่าในการหลีกเลี่ยงการร่ายสองครั้ง:

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

การหลีกเลี่ยงการย่อโค้ดนี้ให้มากที่สุดเท่าที่จะทำได้รวมถึงการหลีกเลี่ยงการร่ายซ้ำของวัตถุเดียวกันทำให้ฉันรำคาญอยู่เสมอ ด้านบนถูกบีบอัดอย่างดีพร้อมการจับคู่รูปแบบกับสิ่งต่อไปนี้:

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

แก้ไข: อัปเดตวิธีการใหม่ที่ยาวขึ้นเพื่อใช้สวิตช์ตามความคิดเห็นของ Palec


1
แนะนำให้ใช้switchคำสั่งที่มีการจับคู่รูปแบบในกรณีนี้
Palec

คุณจะรับมือกับ a อย่างไร? ในบล็อกรหัสนี้โดยเฉพาะ? if (obj1 is int integerValue) { integerValue++; }
Ben Vertonghen

เบ็นถ้าฉันเข้าใจคำถามของคุณฉันก็จะมีคำสั่งอื่นที่จะจัดการกับกรณีอื่น ๆ เนื่องจากคุณไม่สามารถใส่ไม่ใช่จำนวนเต็มลงในตัวแปรจำนวนเต็ม :)
JoelC

14

ฉันมีType- คุณสมบัติเพื่อเปรียบเทียบและไม่สามารถใช้is(เช่นmy_type is _BaseTypetoLookFor) แต่ฉันสามารถใช้สิ่งเหล่านี้:

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

ขอให้สังเกตว่าIsInstanceOfTypeและIsAssignableFromผลตอบแทนtrueเมื่อเทียบประเภทเดียวกันที่ IsSubClassOf falseจะกลับมา และIsSubclassOfไม่ทำงานบนส่วนต่อประสานที่อีกสองตัวทำ (ดูคำถามและคำตอบนี้ด้วย)

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

ฉันชอบคือ

ที่กล่าวว่าหากคุณใช้งานอยู่แสดงว่าคุณไม่ได้ใช้การสืบทอดอย่างเหมาะสม

สมมติว่าบุคคลนั้น: เอนทิตีและสัตว์นั้น: เอนทิตี ฟีดเป็นวิธีเสมือนใน Entity (เพื่อให้ Neil มีความสุข)

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
    }
  }
}

ค่อนข้าง

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

1
จริงฉันจะไม่ทำในอดีตรู้ว่าคนนั้นมาจากสัตว์
jasonh

3
อย่างหลังไม่ได้ใช้มรดกจริงๆ ฟูควรเป็นวิธีเสมือนของเอนทิตีที่ถูกเขียนทับในบุคคลและสัตว์
Neil Williams

2
@bobobobo ฉันคิดว่าคุณหมายถึง "การบรรทุกเกินพิกัด" ไม่ใช่ "การสืบทอด"
lc

@lc: ไม่ฉันหมายถึงการสืบทอด ตัวอย่างแรกเป็นวิธีที่ไม่ถูกต้อง (ใช้คือ ) เพื่อรับพฤติกรรมที่แตกต่าง ตัวอย่างที่สองใช้มากไปใช่ แต่หลีกเลี่ยงการใช้ของมี
bobobobo

1
ปัญหากับตัวอย่างคือมันจะไม่ขยายขนาด หากคุณเพิ่มเอนทิตีใหม่ที่จำเป็นต้องกิน (เช่นแมลงหรือสัตว์ประหลาด) คุณจะต้องเพิ่มวิธีการใหม่ในคลาสเอนทิตี้แล้วแทนที่มันในคลาสย่อยที่จะฟีด นี่ไม่ใช่สิ่งที่ดีไปกว่ารายการถ้า (เอนทิตีคือ X) อื่น ๆ (เอนทิตี้คือ Y) ... สิ่งนี้ละเมิด LSP และ OCP การสืบทอดอาจไม่ใช่วิธีแก้ปัญหาที่ดีที่สุด อาจต้องการรูปแบบการมอบหมายบางรูปแบบ
ebrown

5

ฉันเชื่อว่าคนสุดท้ายดูมรดก (เช่นสุนัขคือสัตว์ == จริง) ซึ่งดีกว่าในกรณีส่วนใหญ่


2

ขึ้นอยู่กับสิ่งที่ฉันทำ ถ้าฉันต้องคุ้มค่าบูล (ที่บอกว่าจะตรวจสอบว่าฉันจะโยนไปเป็น int) isผมจะใช้ ถ้าจริงผมต้องพิมพ์ด้วยเหตุผลบางอย่าง (พูด, การส่งผ่านไปยังบางวิธีอื่น ๆ ) GetType()ผมจะใช้


1
จุดดี. ฉันลืมที่จะพูดถึงว่าฉันได้รับคำถามนี้หลังจากดูคำตอบหลายอย่างที่ใช้คำสั่ง if เพื่อตรวจสอบประเภท
jasonh

0

อันสุดท้ายคือสะอาดขึ้นชัดเจนขึ้นและตรวจสอบชนิดย่อย คนอื่นไม่ได้ตรวจสอบความหลากหลาย


0

ใช้เพื่อรับวัตถุ System.Type สำหรับชนิด การแสดงออก typeof ใช้แบบฟอร์มต่อไปนี้:

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
    */

ตัวอย่างนี้ใช้วิธี GetType เพื่อกำหนดประเภทที่ใช้ในการเก็บผลลัพธ์ของการคำนวณตัวเลข ขึ้นอยู่กับข้อกำหนดในการจัดเก็บของหมายเลขผลลัพธ์

    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
โปรดแก้ไขด้วยข้อมูลเพิ่มเติม รหัสเท่านั้นและคำตอบ "ลองนี้" จะหมดกำลังใจเพราะพวกเขาไม่มีเนื้อหาที่ค้นหาได้และไม่อธิบายว่าทำไมคนควร "ลองนี้"
abarisone

คำตอบของคุณไม่เกี่ยวข้องกับคำถาม
menxin

-5

คุณสามารถใช้โอเปอเรเตอร์ "typeof ()" ใน C # แต่คุณต้องเรียกใช้เนมสเปซโดยใช้ System.IO คุณต้องใช้คีย์เวิร์ด "is" หากคุณต้องการตรวจสอบประเภท


7
typeofไม่ได้กำหนดในเนมสเปซมันเป็นคำหลัก System.IOไม่มีอะไรเกี่ยวข้องกับเรื่องนี้
Arturo Torres Sánchez

-5

ประเภทการทดสอบประสิทธิภาพของ () 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();
    }
}

ผลลัพธ์ในโหมดแก้ไขข้อบกพร่อง:

00:00:08.4096636
00:00:10.8570657

ผลลัพธ์ในโหมดเผยแพร่:

00:00:02.3799048
00:00:07.1797128

1
หนึ่งไม่ควรใช้ DateTime.UtcNow สำหรับการวัดประสิทธิภาพ ด้วยรหัสของคุณ แต่กับคลาสนาฬิกาจับเวลาฉันได้ผลลัพธ์ที่ตรงข้ามกับโหมด Debug UseTypeOf: 00: 00: 14.5074469 UseGetType: 00: 00: 10.5799534 โหมดการวางจำหน่ายจะเหมือนกันตามที่คาดไว้
Alexey Shcherbak

@AlexeyShcherbak ความแตกต่างระหว่าง Stopwatch กับ DateTime ขณะนี้ต้องไม่เกิน 10-20 ms ตรวจสอบรหัสของคุณอีกครั้ง และฉันไม่สนเกี่ยวกับมิลลิวินาทีในการทดสอบของฉัน รหัสของฉันก็จะเป็นรหัสอีกหลายบรรทัดด้วย Stopwatch
Alexander Vasilyev

1
เป็นการปฏิบัติที่ไม่ดีโดยทั่วไปไม่ใช่ในกรณีของคุณ
Alexey Shcherbak

4
@AlexanderVasilyev จำนวนบรรทัดของรหัสไม่ควรนำมาใช้เป็นอาร์กิวเมนต์เพื่อทำอะไรบางอย่างที่ทำให้เข้าใจผิดเอกสาร เท่าที่เห็นในmsdn.microsoft.com/en-us/library/system.datetime(v=vs.110).aspx , DateTimeไม่ควรใช้ถ้าคุณกำลังกังวลเกี่ยวกับด้านล่างครั้ง100msเนื่องจากใช้ระยะเวลาของ OS เปรียบเทียบกับStopwatchซึ่งใช้โปรเซสเซอร์ ' Tickความละเอียดที่ใช้โดยDateTimeใน Win7 เป็นไอกรน 15ms
Eric Wu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.