Подтвердить что ты не робот

Наиболее эффективный способ проверить, является ли объект типом значения

ПРЕДУПРЕЖДЕНИЕ: НАСТОЯЩИЕ УКАЗАНИЯ КОДА, ПОСМОТРЕТЬ ЭНТОННЫЕ КОММЕНТАРИИ

Что быстрее?

1.

  public bool IsValueType<T>(T obj){
       return obj is ValueType;
  }

2.

  public bool IsValueType<T>(T obj){
       return obj == null ? false : obj.GetType().IsValueType;
  } 

3.

  public bool IsValueType<T>(T obj){
       return default(T) != null;
  }

4.Что-то еще

4b9b3361

Ответ 1

Вы действительно не тестируете объект - вы хотите проверить тип. Чтобы вызвать их, вызывающий должен знать тип, но... meh. Учитывая подпись <T>(T obj), единственным разумным ответом является:

public bool IsValueType<T>() {
    return typeof(T).IsValueType;
}

или если мы хотим использовать пример объекта для целей вывода типа:

public bool IsValueType<T>(T obj) {
    return typeof(T).IsValueType;
}

для этого не требуется бокс (GetType() - бокс) и не имеет проблем с Nullable<T>. Более интересным является случай, когда вы проходите object...

 public bool IsValueType(object obj);

здесь у нас уже есть серьезные проблемы с null, так как это может быть пустая Nullable<T> (a struct) или класс. Но разумная попытка:

public bool IsValueType(object obj) {
    return obj != null && obj.GetType().IsValueType;
}

но обратите внимание, что он неправильный (и нефиксируемый) для пустых Nullable<T> s. Здесь становится бессмысленным беспокоиться о боксе, поскольку мы уже в коробке.

Ответ 2

Мой первый ответ - написать простой тест и узнать сами.

Мой второй ответ (без какого-либо тестирования с моей стороны, конечно) был бы опцией 1. Это простейшая проверка. Второй метод включает в себя два отдельных проверки, в то время как третий включает создание экземпляра по умолчанию для типа.

Вы также должны учитывать читаемость. Структура уже дает вам возможность иметь следующее в вашем коде:

if(someObj is ValueType)
{
    // Do some work
}

Почему бы даже не создать метод, который просто превратил бы указанный выше оператор (предполагая, что вы сделали свой статический метод и позволили компилятору вывести общий тип):

if(IsValueType(someObj))
{
    // Do some work
}

Ответ 3

Определение структуры на самом деле определяет два типа: тип значения и тип класса, который происходит от System.ValueType. Если создается запрос на создание переменной, параметра, поля или массива (в совокупности "место хранения" ) типа, который происходит из System.ValueType, система вместо этого создаст место хранения, в котором будут храниться поля объекта, а не сохраняя ссылку на объект, в котором появляются эти поля. С другой стороны, если создается запрос на создание экземпляра типа, полученного из System.ValueType, система создаст экземпляр объекта класса, который происходит из System.ValueType.

Это можно продемонстрировать, создав структуру, которая реализует IValue:

interface IValue {int value {get; set;}};
struct ValueStruct : IValue
{
  public int value {get; set;}};
}

с общей тестовой программой и кодом для ее переноса:

static void Test<T>(T it) where T:IValue
{
  T duplicate = it;
  it.value += 1;
  duplicate.value += 10;
  Console.WriteLine(it.value.ToString());
}
static void Test()
{
  ValueStruct v1 = new ValueStruct();
  v1.value = 9;
  IValue v2 = v1;
  Test<ValueStruct>(v1); 
  Test<ValueStruct>(v1); 
  Test<IValue>(v1); 
  Test<IValue>(v1); 
  Test<IValue>(v2);
  Test<IValue>(v2);
}

Обратите внимание, что в каждом случае вызов GetType по параметру, переданному Test, приведет к ValueStruct, который будет сообщать себя как тип значения. Тем не менее, переданный элемент будет только "реальным" типом значения при первых двух вызовах. На третьем и четвертом вызовах это будет действительно тип класса, о чем свидетельствует тот факт, что изменение на duplicate повлияет на it. И на пятом и шестом вызовах это изменение будет передано обратно на v2, поэтому второй вызов будет "видеть" его.

Ответ 4

static class Metadata<T>
{
    static public readonly Type Type = typeof(T);
    static public readonly bool IsValueType = Metadata<T>.Type.IsValueType;
}

//fast test if T is ValueType
if(Metadata<T>.IsValueType) //only read static readonly field!
{
    //...
}

Ответ 5

Существует два правила:

1-Все классы - это ссылочные типы, такие как Object и String, поэтому они поддерживаются .NET Framework classes.

Структуры 2-All - это значение, такие как bool и char, хотя он содержит ссылочный элемент, поэтому он поддерживается .NET Framework структуры.. p >

Просто щелкните правой кнопкой мыши по любому типу и Перейти к определению, если это класс, поэтому он означает ссылочный тип else, если он является Struct, поэтому он означает тип значения:)