Как узнать, является ли тип "простым"? т.е. имеет единственное значение
typeof(string).IsPrimitive == false
typeof(int).IsPrimitive == true
typeof(MyClass).IsClass == true
typeof(string).IsClass == true
typeof(string).IsByRef == false
typeof(MyClass).IsByRef == true // correction: should be false (see comments below)
У меня есть метод, который создает экземпляр нового экземпляра T и, если он является "сложным" классом, заполняет его свойства из набора значений исходных данных.
(a) Если T - простой тип (например, строка или int или что-то еще подобное), необходимо выполнить быстрое преобразование из исходных данных в T.
(b) Если T - класс (но не что-то простое, как строка), то я буду использовать Activator.CreateInstance и немного отразить, чтобы заполнить поля.
Есть ли простой и простой способ сказать, следует ли мне использовать метод (a) или метод (b)? Эта логика будет использоваться внутри общего метода с T как аргументом типа.
Ответы
Ответ 1
Строка, вероятно, является особым случаем.
Я думаю, что буду делать.....
bool IsSimple(Type type)
{
return type.IsPrimitive
|| type.Equals(typeof(string)));
}
Edit:
Иногда вам нужно прикрывать еще несколько случаев, например перечисления и десятичные числа. Перечисления - это особый тип типа в С#. Десятичные числа - это структуры, как и любые другие. Проблема с структурами заключается в том, что они могут быть сложными, они могут быть определенными пользователем типами, они могут быть просто числом. Таким образом, у вас нет другого шанса, чем знать, что они должны различать.
bool IsSimple(Type type)
{
return type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
Обработка совпадающих с нулями эквивалентов также немного сложна. Сама с нулевым значением является структурой.
bool IsSimple(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// nullable type, check if the nested type is simple.
return IsSimple(type.GetGenericArguments()[0]);
}
return type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
Тест:
Assert.IsTrue(IsSimple(typeof(string)));
Assert.IsTrue(IsSimple(typeof(int)));
Assert.IsTrue(IsSimple(typeof(decimal)));
Assert.IsTrue(IsSimple(typeof(float)));
Assert.IsTrue(IsSimple(typeof(StringComparison))); // enum
Assert.IsTrue(IsSimple(typeof(int?)));
Assert.IsTrue(IsSimple(typeof(decimal?)));
Assert.IsTrue(IsSimple(typeof(StringComparison?)));
Assert.IsFalse(IsSimple(typeof(object)));
Assert.IsFalse(IsSimple(typeof(Point))); // struct in System.Drawing
Assert.IsFalse(IsSimple(typeof(Point?)));
Assert.IsFalse(IsSimple(typeof(StringBuilder))); // reference type
Ответ 2
В дополнение к Stefan Steinegger ответ:
В .NET Core.IsPrimitive и т.д. Больше не являются членами Type, они теперь являются членами TypeInfo. Поэтому его решение станет следующим:
bool IsSimple(TypeInfo type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
// nullable type, check if the nested type is simple.
return IsSimple((type.GetGenericArguments()[0]).GetTypeInfo());
}
return type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal));
}
Ответ 3
Существует более общий тип, чем примитив, ValueType включает в себя гораздо больше, чем примитивный, например перечисления, десятичные и другие подобные вещи ValueType. Ниже приведена функция, которую я написал для определения сложных типов, которые могут соответствовать вашим потребностям.
public static bool IsComplex(Type typeIn)
{
if (typeIn.IsSubclassOf(typeof(System.ValueType)) || typeIn.Equals(typeof(string))) //|| typeIn.IsPrimitive
return false;
else
return true;
}
Ответ 4
Извините, что воскресил действительно старый поток, но поскольку он по-прежнему высоко ценит веб-поиск в Google, вы хотите получить более прямое и эффективное решение:
if(System.Type.GetTypeCode(typeof(int)) == TypeCode.Object) {
// Do what you will...
}
Ответ 5
Возможно, это не имеет значения, но похоже, что вы оставляете несколько случаев:
- Сложные типы, имеющие преобразования
- Типы значений, у которых нет конструктора без параметров. Пример ниже:
Есть, вероятно, больше, но я думаю, что вы разбиваете проблемное пространство чрезмерно ограничительным образом.
public class Person {
private string _name;
private int _age;
public Person(string name, int age) {_name = name; _age = age;}
// Remainder of value implementation
}
Ответ 6
Строки не примитивы, если я правильно помню. хотя для него есть ключевое слово, строка - это объект. Ваш вызов IsPrimitive точно скажет вам, является ли что-то примитивным.