Ответ 1
Имейте в виду, что значение по умолчанию (строка) равно null, а не string.Empty. Вам может понадобиться специальный код в вашем коде:
if (typeof(T) == typeof(String)) return (T)(object)String.Empty;
У меня есть общий класс, который должен допускать любой тип, примитив или иначе. Единственная проблема с этим - использовать 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>();
}
}
Но это похоже на клочья. Есть ли более удобный способ обработки строки?
Имейте в виду, что значение по умолчанию (строка) равно null, а не string.Empty. Вам может понадобиться специальный код в вашем коде:
if (typeof(T) == typeof(String)) return (T)(object)String.Empty;
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();
}
}
Обсуждение для 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>();
}
}
}