У меня есть общий класс, который должен разрешать любой тип, примитивный или другой. Единственная проблема с этим - использование default(T)
. Когда вы вызываете default для типа значения или строки, он инициализирует его разумным значением (например, пустой строкой). Когда вы вызываете default(T)
объект, он возвращает null. По разным причинам нам необходимо убедиться, что если это не примитивный тип, то у нас будет экземпляр типа по умолчанию, а не 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>();
}
}
Но это похоже на лабиринт. Есть ли лучший способ справиться со строкой?
is
ключевого слова? Разве это не нужно здесь?if (typeof(T).IsValueType || typeof(T) == typeof(String)) { return default(T); } else { return Activator.CreateInstance<T>(); }
Не тестировал, но первое, что пришло в голову.
источник
Вы можете использовать перечисление TypeCode . Вызовите метод GetTypeCode для классов, реализующих интерфейс IConvertible, чтобы получить код типа для экземпляра этого класса. IConvertible реализуется с помощью Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char и String, поэтому вы можете проверять примитивные типы, используя это. Дополнительная информация о « Проверка общего типа ».
источник
Лично мне нравится перегрузка методов:
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(); } }
источник
Я знаю, что это старый вопрос, но было обновление.
Начиная с C # 7.0, вы можете использовать
is
оператор для сравнения типов. Вам больше не требуется использоватьtypeof
as в принятом ответе.public bool IsObjectString(object obj) { return obj is string; }
https://docs.microsoft.com/en-US/dotnet/csharp/language-reference/keywords/is
источник
Обсуждение 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>(); } } }
источник
String
по имени, особенно без учета пространства имен, - это плохо. И мне тоже не нравится, как вы обращаетесь.