2016-12-10 3 views
3

У меня есть метод, он не имеет никаких параметров T.C# typeof применяется к универсальному параметру supertype

К сожалению, оператор C# typeof не работает с генераторами, как показано ниже.

public static string ToString(object obj) 
{ 
    if (obj.GetType() == typeof(List<object>)) 
    { 
     return "Bug: Never called"; 
    } 
    if (obj.GetType() == typeof(List<int>)) 
    { 
     return "Method only works for int lists"; 
    } 
    return ""; 
} 

Ожидаемый результат: ToString (List of ints) вернет «Ошибка: никогда не был вызван».

Фактический выход: «Метод работает только для списков Int»

Это работает прекрасно в Java. Вы скажете, что дженерики в C# не поддерживают это. Как я могу реструктурировать свой код, чтобы заставить метод «ToString (object)» использовать список объектов?

Требования: Вы не можете изменить подпись метода, а только его реализацию.

К сожалению, вы не можете реализовать класс «int» с интерфейсом. Поскольку класс int был написан Microsoft. Поэтому я не могу добавить шаблон посетителя в тип int.

+0

Почему вы ожидаете 'List ' return 'Bug: Never Called, который является веткой для 'List '? –

+2

Я не понимаю, почему вы ожидаете, что тип 'List ' объект будет 'List '. Да, это то, что делает Java, но C# - это не Java. Возможно, поведение Java не то, что ожидают большинство людей. Я думаю, вы могли бы использовать GetGenericTypeDefintion и сравнить с 'typeof (List <>)', чтобы увидеть, если это список чего-то. –

+0

Поскольку объект является суперклассом int. Я думал, что объект также «захватывает» int. – user2186597

ответ

4

К сожалению, оператор C# typeof не работает на дженериках, как показано ниже.

На самом деле, весьма удачно, что он не работает, поскольку вы ожидаете его работы. В отличие от Java, C# отличает от List<int> и List<object> во время выполнения, не только во время компиляции. Информация типа для генериков, созданных с помощью примитивных параметров типа, позволяет .NET создавать более эффективный код, избегая стирания типов.

Если вы хотите, чтобы проверить, является ли объект любых общего списка, используйте эту проверку вместо:

var objT = obj.GetType(); 
if (objT.IsGenericType && objT.GetGenericTypeDefinition() == typeof(List<>)) { 
    ... 
} 

Как таковой я не могу добавить шаблон посетителя на int типа.

C# дает мощный механизм для динамического диспетчеризации без реализации интерфейса. Например, вы можете сделать это:

public static string ToString(object obj) { 
    var list = obj as IList; 
    if (list != null) { 
     foreach (dynamic o in list) { 
      Process(o); 
     } 
    } 
} 
static void Process(int n) { ... } 
static void Process(string s) { ... } 
static void Process(object o) { ... } 

выше будет выбрать правильную реализацию Process на основе типа времени выполнения объекта в списке.

+0

Отлично, вы ответили на первую часть вопроса, почему не работает C# generics. Теперь для второй части вопроса: я хочу только единообразно манипулировать списком, независимо от базового типа. – user2186597

+0

Любой общий ** список **: D –

+0

dasblinkenlight, thats nice, но casting выдаст исключение, если базовый объект не является списком. Вот почему я сосредоточился на «условии». – user2186597

Смежные вопросы