C # /. NET: Является ли `typeof (переменная)` возможной функцией языка? - PullRequest
9 голосов
/ 08 ноября 2010

Несколько раз я пытался вытолкнуть объявленный тип из переменной, относительно далеко от ее объявления, только чтобы выяснить, что typeof(T) работает только с именами типов.

Я былинтересно, будут ли какие-либо критические изменения, чтобы разрешить typeof(variable).

Например, с этим кодом:

class Animal { /* ... */ }
class Goat : Animal { /* ... */ }

/* ... */

var g = new Goat();
Animal a = g;

Console.WriteLine(typeof(Goat));
Console.WriteLine(typeof(Animal));
Console.WriteLine(g.GetType());
Console.WriteLine(a.GetType());

Вы получите что-то вроде:

Коза
Животное
Коза
Коза

Почему это невозможно сделать:

Console.WriteLine(typeof(g));
Console.WriteLine(typeof(a));

Коза
Животное

Я бегло посмотрел на спецификацию и не могу найти никакого конфликта.Я думаю, что это прояснит вопрос "Почему этот тип?"при использовании оператора typeof.

Я знаю, что компилятор способен, здесь.Реализация с использованием методов расширения на самом деле тривиальна:

public static Type TypeOf<T>(this T variable)
{
    return typeof(T);
}

Но это выглядит грязно, злоупотребляя выводом типа компилятора.

Ответы [ 5 ]

4 голосов
/ 08 ноября 2010

Я думаю, что проблема здесь в том, что .GetType () старше, чем typeof (). Раньше в C # был день, когда нужно было сделать

"0".GetType()

для того, чтобы получить тип String (например), пока не был создан typeof (). Я думаю, что если бы эта концепция была частью оригинального языкового дизайна, тогда она действительно могла бы работать так, как вы описываете. Поскольку typeof () является поздним введением в язык, тогда дизайнерам пришлось сделать выбор: Устаревший / устареть / удалить. GetType () (и в процессе этого многие, многие его применения устарели), сделать typeof () перекрывайте функциональность с помощью GetType () (о чем вы и просите), или сделайте так, чтобы использование typeof () не перекрывалось с GetType (). Я думаю, что люди на C # просто решили не перекрывать функциональность (чтобы все было просто и понятно), и поэтому typeof () был ограничен таким, каким он является сегодня.

3 голосов
/ 08 ноября 2010

Предположим, это разрешено:

class Animal { }

string Animal;
Type t = typeof(Animal); // uh-oh!
0 голосов
/ 13 мая 2015

Когда я хочу это сделать, я использую Convert.ChangeType()

https://msdn.microsoft.com/en-us/library/system.convert.changetype%28v=vs.110%29.aspx

0 голосов
/ 08 ноября 2010

Вы, похоже, задаете два разных вопроса: первый - почему нет оператора для поиска объявленного типа переменной, а другой - почему typeof (o) не может быть эквивалентом o.GetType () .

Во-первых, причина в том, что это не имеет смысла, объявленный тип переменной по определению всегда известен во время компиляции. Добавление оператора для него не добавит значения.

С другой стороны, проблема в том, что использование typeof (instance) вызывает проблемы с разрешением. Как упоминал Джейсон выше, рассмотрим:

public class Animal {}
string Animal;
Type t = typeof(Animal);

Что такое т? Если вы трактуете t как typeof (string) , то вы просто добавляете в язык существенные критические изменения. Представьте себе весь код, который в настоящее время предполагает, что t является Animal, что в настоящее время правильно.

Если вы рассматриваете t как typeof (Animal) , тогда ваш код невероятно хрупок. Представьте себе ситуацию, когда не было класса Animal, когда вы писали код, но год спустя кто-то добавил класс Animal в какое-то пространство имен, которое вы импортировали. Ваш код будет поврежден, потому что правила разрешения теперь будут использовать тип Animal, а не локальную переменную.

0 голосов
/ 08 ноября 2010

Если вы просто пытаетесь получить тип чего-либо, вы можете просто позвонить

Type t1 = myObject.GetType();

, которое должно соответствовать желаемому поведению.

...