Лучший способ проверить, является ли универсальный тип строкой? (С #) - PullRequest
85 голосов
/ 28 августа 2008

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

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>();
    }
}

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

Ответы [ 5 ]

147 голосов
/ 28 августа 2008

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

if (typeof(T) == typeof(String)) return (T)(object)String.Empty;
14 голосов
/ 28 августа 2008
if (typeof(T).IsValueType || typeof(T) == typeof(String))
{
     return default(T);
}
else
{
     return Activator.CreateInstance<T>();
}

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

4 голосов
/ 28 августа 2008

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

2 голосов
/ 10 февраля 2015

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

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();
  }
}
0 голосов
/ 13 февраля 2011

Обсуждение для 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>();
            } 
        } 

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...