Как я могу получить тип данных переменной в 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
Джеймик прав. Статическая типизация означает, что объявление устанавливает ваш тип навсегда. Ваша переменная 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для получения объекта типа во время выполнения для статического типа.
— phoog

да, я знаю статический тип = тип времени компиляции и тип времени выполнения = динамический тип. Хотя вы получаете тип переменной '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 06


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

Просто наведите курсор на интересующего вас члена и посмотрите всплывающую подсказку - она ​​покажет тип члена:

введите описание изображения здесь



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.