Як я можу отримати тип даних змінної в C #?


92

Як я можу дізнатись, який тип даних містить якась змінна? (наприклад, 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
Джамієк має рацію. Статичне введення означає, що декларація встановлює ваш тип назавжди. Ваша змінна n може бути лише того типу, який ви оголосили, або успадкованого типу. У вашому конкретному випадку ви вибрали відображення int, це тип, від якого ви не можете успадкувати, тому n може бути лише int.
Ksempac

Відповіді:


119

Є важливе і тонке питання, яке жоден з них не вирішує безпосередньо. Існує два способи розгляду типу в 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щоб отримати об'єкт типу під час виконання для статичного типу.
phoog

так, я знаю static type = тип компіляції та type runtime = динамічний тип. Хоча отримуючи тип змінної '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


16

Взагалі кажучи, вам навряд чи доведеться робити порівняння типів, якщо ви не робите щось із відображенням або інтерфейсами. Тим не менше:

Якщо вам відомий тип, з яким ви хочете його порівняти, використовуйте оператори isor 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();
}



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

GetType() метод

int n=34;
Console.WriteLine(n.GetType());
string name="Smome";
Console.WriteLine(name.GetType());

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.");
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.