Лучший способ проверить, является ли общий тип строкой? (С#)

У меня есть общий класс, который должен допускать любой тип, примитив или иначе. Единственная проблема с этим - использовать 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>();
    }
}

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

    }