ฉันจะรับชนิดข้อมูลของตัวแปรใน C # ได้อย่างไร


96

ฉันจะทราบได้อย่างไรว่าตัวแปรบางตัวมีข้อมูลประเภทใดอยู่ (เช่น int, string, char ฯลฯ )

ฉันมีสิ่งนี้ตอนนี้:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Testing
{
    class Program
    {
        static void Main()
        {
            Person someone = new Person();
            someone.setName(22);
            int n = someone.getName();
            Console.WriteLine(n.typeOf());
        }
    }

    class Person
    {
        public int name;

        public void setName(int name)
        {
            this.name = name;
        }

        public int getName()
        {
            return this.name;
        }
    }
}

6
คุณได้กำหนดประเภทไว้แล้ว -int
Jamiec

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

1
นอกเรื่อง แต่สิ่งที่คุณเขียนที่นี่ดีกว่าเขียนแบบนี้ด้วย C #: class Person { public string Name { get; set; } }หรือclass Person { private string m_Name; public string Name { get {return m_Name;} set { m_Name = value; } }. อ่านเอกสารเกี่ยวกับProperties
Steve B

1
Jamiec พูดถูก การพิมพ์แบบคงที่หมายถึงการประกาศกำหนดประเภทของคุณตลอดไป ตัวแปร n ของคุณสามารถเป็นประเภทที่คุณประกาศหรือประเภทที่สืบทอดมาเท่านั้น ในกรณีเฉพาะของคุณคุณเลือกที่จะแสดง int ซึ่งเป็นประเภทที่คุณไม่สามารถสืบทอดได้ดังนั้น n จึงเป็นได้เฉพาะ int
Ksempac

คำตอบ:


124

มีประเด็นสำคัญและละเอียดอ่อนที่ไม่มีประเด็นใดกล่าวถึงโดยตรง มีสองวิธีในการพิจารณาประเภทใน C #: ประเภทคงที่และประเภทเวลาทำงาน

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

คุณสามารถรับประเภทคงที่ได้โดยการเขียนวิธีการทั่วไปของผู้ช่วยเพื่อให้การอนุมานประเภทดูแลคุณ:

   Type GetStaticType<T>(T x) { return typeof(T); }

ประเภทรันไทม์คือประเภทของวัตถุในหน่วยความจำ จึงเป็นแนวคิดรันไทม์ นี่คือประเภทที่ส่งคืนโดยGetType()วิธีการ

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

object o = "Some string";

ประเภทคงที่ของตัวแปรobjectแต่ในเวลาทำงานประเภทของตัวแปรที่อ้างอิงstringเป็น ดังนั้นบรรทัดถัดไปจะพิมพ์ "System.String" ไปที่คอนโซล:

Console.WriteLine(o.GetType()); // prints System.String

แต่ถ้าคุณวางเมาส์เหนือตัวแปรoในสภาพแวดล้อมการพัฒนาของคุณคุณจะเห็นประเภทSystem.Object(หรือobjectคำหลักที่เทียบเท่า) คุณจะเห็นสิ่งเดียวกันโดยใช้ฟังก์ชันตัวช่วยของเราจากด้านบน:

Console.WriteLine(GetStaticType(o)); // prints System.Object

สำหรับตัวแปรค่าชนิดเช่นint, double, System.Guidคุณรู้ว่าชนิดเวลาทำงานจะเป็นเช่นเดียวกับประเภทคงเพราะค่าชนิดไม่สามารถทำหน้าที่เป็นชั้นฐานสำหรับประเภทอื่น ประเภทค่าได้รับการรับรองว่าเป็นประเภทที่ได้รับมากที่สุดในสายการสืบทอด นี้ยังเป็นจริงชนิดปิดผนึกอ้างอิง: nullถ้าประเภทคงเป็นชนิดปิดผนึกอ้างอิงค่าเวลาทำงานอย่างใดอย่างหนึ่งจะต้องเป็นตัวอย่างของประเภทนั้นหรือ

ในทางกลับกันหากประเภทคงที่ของตัวแปรเป็นประเภทนามธรรมก็รับประกันได้ว่าประเภทคงที่และประเภทรันไทม์จะแตกต่างกัน

เพื่อแสดงให้เห็นว่าในรหัส:

// int is a value type
int i = 0;
// Prints True for any value of i
Console.WriteLine(i.GetType() == typeof(int));

// string is a sealed reference type
string s = "Foo";
// Prints True for any value of s
Console.WriteLine(s == null || s.GetType() == typeof(string));

// object is an unsealed reference type
object o = new FileInfo("C:\\f.txt");
// Prints False, but could be true for some values of o
Console.WriteLine(o == null || o.GetType() == typeof(object));

// FileSystemInfo is an abstract type
FileSystemInfo fsi = new DirectoryInfo("C:\\");
// Prints False for all non-null values of fsi
Console.WriteLine(fsi == null || fsi.GetType() == typeof(FileSystemInfo));

3
ดังนั้น variable.getType()ส่งคืนประเภทรันไทม์ (ประเภทด้านขวามือ) แต่สิ่งที่ส่งคืนประเภทคงที่ (ประเภทด้านซ้ายมือของตัวแปร)?
barlop

@barlop ที่ทราบเวลาคอมไพล์ คุณสามารถใช้typeofเพื่อรับวัตถุประเภทที่รันไทม์สำหรับประเภทคงที่
กลัว

ใช่ฉันรู้จักประเภทคงที่ = ประเภทเวลาคอมไพล์และประเภทรันไทม์ = ประเภทไดนามิก แม้ว่าจะได้รับประเภทของตัวแปร 'a' แต่คุณไม่สามารถทำได้typeof(a) หากคุณทำtypeof(int)มันจะส่งคืน int แต่ไม่ได้ตรวจสอบตัวแปร 'a' และแสดงประเภทของ 'a' .. คุณสามารถพูดได้ว่าคุณ ไม่จำเป็นต้องแสดงประเภทคงที่ของ 'a' ซึ่งอาจเป็นเช่นนั้น แต่ความจริงก็คือมันไม่ได้แสดง ผมจึงไม่เห็นว่าการใช้ typeof ตรงนี้มีประโยชน์อย่างไร
barlop

4
@barlop คุณสามารถทำสิ่งนี้เพื่อให้การอนุมานประเภทดูแลคุณได้:Type GetStaticType < T > (T x) { return typeof(T); }
phoog

1
@Jaquarh อย่างที่คุณสังเกตเห็นswitchตอนนี้รองรับการจับคู่รูปแบบสำหรับการทดสอบประเภท (ของประเภทรันไทม์ไม่ใช่แบบคงที่) แทนที่จะเปิดค่าที่ส่งกลับจาก GetType () คุณจะเปิดตัวแปรโดยตรง
phoog

19

มันง่ายมาก

variable.GetType().Name

มันจะส่งคืนประเภทข้อมูลของตัวแปรของคุณ


16

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

หากคุณทราบประเภทที่ต้องการเปรียบเทียบให้ใช้isหรือasโอเปอเรเตอร์:

if( unknownObject is TypeIKnow ) { // run code here

asผู้ประกอบการดำเนินการหล่อที่ผลตอบแทนเป็นโมฆะถ้ามันล้มเหลวมากกว่าข้อยกเว้น:

TypeIKnow typed = unknownObject as TypeIKnow;

หากคุณไม่ทราบประเภทและต้องการข้อมูลประเภทรันไทม์ให้ใช้เมธอด. GetType ():

Type typeInformation = unknownObject.GetType();

ใน C # เวอร์ชันใหม่กว่าคุณสามารถใช้ตัวisดำเนินการเพื่อประกาศตัวแปรโดยไม่จำเป็นต้องใช้as:

if( unknownObject is TypeIKnow knownObject ) {
    knownObject.SomeMember();
}

ก่อนหน้านี้คุณจะต้องทำสิ่งนี้:

TypeIKnow knownObject;
if( (knownObject = unknownObject as TypeIKnow) != null ) {
    knownObject.SomeMember();
}

4

เพียงวางเคอร์เซอร์ไว้เหนือสมาชิกที่คุณสนใจและดูคำแนะนำเครื่องมือ - มันจะแสดงประเภทของ memeber:

ป้อนคำอธิบายภาพที่นี่



3

ทางเลือกหนึ่งคือการใช้วิธีการขยายตัวช่วยดังนี้:

public static class MyExtensions
{
    public static System.Type Type<T>(this T v)=>typeof(T);
}

var i=0;
console.WriteLine(i.Type().FullName);


0

ลองดูหนึ่งในวิธีง่ายๆในการดำเนินการนี้

// Read string from console
        string line = Console.ReadLine(); 
        int valueInt;
        float valueFloat;
        if (int.TryParse(line, out valueInt)) // Try to parse the string as an integer
        {
            Console.Write("This input is of type Integer.");
        }
        else if (float.TryParse(line, out valueFloat)) 
        {
            Console.Write("This input is of type Float.");
        }
        else
        {
            Console.WriteLine("This input is of type string.");
        }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.