2008-08-28 2 views
78

У меня есть общий класс, который должен допускать любой тип, примитив или иное. Единственная проблема с этим - использование default(T). Когда вы вызываете default по типу значения или строке, он инициализирует его до разумного значения (например, пустую строку). Когда вы вызываете default(T) на объект, он возвращает null. По разным причинам нам нужно убедиться, что если это не примитивный тип, то у нас будет экземпляр по умолчанию типа, не null. Вот попытка 1:Лучший способ проверить, является ли общий тип строкой? (C#)

T createDefault() 
{ 
    if(typeof(T).IsValueType) 
    { 
     return default(T); 
    } 
    else 
    { 
     return Activator.CreateInstance<T>(); 
    } 
} 

Проблема - строка не тип значения, но она не имеет конструктора без параметров. Таким образом, текущее решение:

T createDefault() 
{ 
    if(typeof(T).IsValueType || typeof(T).FullName == "System.String") 
    { 
     return default(T); 
    } 
    else 
    { 
     return Activator.CreateInstance<T>(); 
    } 
} 

Но это похоже на клочья. Есть ли лучший способ справиться с строкой?

ответ

133

Имейте в виду, что значение по умолчанию (строка) равно null, а не string.Empty. Вы можете специальный случай в вашем коде:

if (typeof(T) == typeof(String)) return (T)(object)String.Empty; 
+2

Я думал, что я пытался это решение раньше, и это не сработало, но я, должно быть, сделал что-то глупое. И спасибо, что указали, что default (string) возвращает null, из-за этого мы еще не запутались в ошибке, но это правда. – 2010-05-29 00:32:26

+1

@Matt Hamilton: +1, но вы должны обновить свой ответ, чтобы вернуть '(T) (объект) String.Empty', как это было предложено CodeInChaos, потому что тип возвращаемого метода является общим, вы не можете просто вернуть строку. – VoodooChild 2012-01-23 17:04:09

13
if (typeof(T).IsValueType || typeof(T) == typeof(String)) 
{ 
    return default(T); 
} 
else 
{ 
    return Activator.CreateInstance<T>(); 
} 

Непрошеный, но первое, что пришло в голову.

4

Вы можете использовать TypeCode перечисление. Вызвать метод GetTypeCode для классов, реализующих интерфейс IConvertible, для получения кода типа для экземпляра этого класса. IConvertible реализуется с помощью Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char и String, поэтому вы можете проверить их на примитивные типы. Дополнительная информация о "Generic Type Checking".

-6

Обсуждение для String здесь не работает.

я должен был иметь следующий код для дженериков, чтобы заставить его работать -

private T createDefault() 
    { 

     {  
      if(typeof(T).IsValueType)  
      {   
       return default(T);  
      } 
      else if (typeof(T).Name == "String") 
      { 
       return (T)Convert.ChangeType(String.Empty,typeof(T)); 
      } 
      else 
      { 
       return Activator.CreateInstance<T>(); 
      } 
     } 

    } 
2

Лично мне нравится метод перегрузки:

public static class Extensions { 
    public static String Blank(this String me) {  
    return String.Empty; 
    } 
    public static T Blank<T>(this T me) {  
    var tot = typeof(T); 
    return tot.IsValueType 
     ? default(T) 
     : (T)Activator.CreateInstance(tot) 
     ; 
    } 
} 
class Program { 
    static void Main(string[] args) { 
    Object o = null; 
    String s = null; 
    int i = 6; 
    Console.WriteLine(o.Blank()); //"System.Object" 
    Console.WriteLine(s.Blank()); //"" 
    Console.WriteLine(i.Blank()); //"0" 
    Console.ReadKey(); 
    } 
} 
Смежные вопросы