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

Обнаружение Nullable Type посредством отражения

Удивительно, что следующий код не сбрасывает Assert:

int? wtf = 0;
Assert.IsType<Nullable<int>>(wtf);

Так просто из любопытства, как вы можете определить, является ли данный экземпляр объектом Nullable < > или нет?

4b9b3361

Ответ 1

Хорошо, во-первых, Nullable<T> - это структура, поэтому нет объекта как такового. Вы не можете вызвать GetType(), так как это приведет к значению (в этот момент вы либо получите нуль, и, таким образом, исключение, или значение, не равное нулю, и, следовательно, не тот тип, который вы хотите).

(Бокс - это то, что испортило ваше утверждение здесь - я бы предположил, что IsType принимает object.)

Вы можете использовать вывод типа, хотя для получения типа переменной в качестве параметра типа:

public bool IsNullable<T>(T value)
{
    return Nullable.GetUnderlyingType(typeof(T)) != null;
}

Это не огромное количество использования, когда вы знаете точный тип во время компиляции, как в вашем примере, но это полезно для дженериков. (Конечно, есть альтернативные способы его реализации.)

Какова ваша реальная жизненная ситуация? Я предполагаю, что это не утверждение, подобное этому, учитывая, что вы знаете ответ на этот вопрос во время компиляции.

Ответ 2

Мне нравится ответ @jon-skeet, но он работает только, если вы знаете тип, с которым вы тестируете. В нашем мире мы используем отражение, чтобы открывать объекты и тестировать значения в выражениях регулярных выражений.

упрощение расширения для работы для любого типа, работающего лучше для нас.

public static bool IsNullable(this Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}

дженерики - это кровь жизни, но иногда...:)

Ответ 3

int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
    type.GetGenericTypeDefinition() == typeof(Nullable<>);

Ответ 4

Какое пространство имен Assert в?

Возвращает true, как и следовало ожидать:

int? wtf = 0;
if (typeof(Nullable<int>).IsInstanceOfType(wtf))
{
    // Do things
}

Хотя стоит отметить, что typeof(Nullable<int>).IsInstanceOfType(42) также возвращает true - это потому, что этот метод принимает object и поэтому получает коробку как Nullable<int>.

Ответ 5

Вот что я придумал, поскольку все остальное, казалось, потерпело неудачу - по крайней мере, в Portable Class Library/DotNet Core s >= С# 6

В основном вы расширяете общий тип Object и Nullable<T> и используете тот факт, что статический метод расширения, соответствующий базовому типу, будет вызываться и имеет приоритет над общим методом T.

public static partial class ObjectExtension
{
    public static bool IsNullable<T>(this T self)
    {
        return false;
    }
}

и один для Nullable<T>

public static partial class NullableExtension
{
    public static bool IsNullable<T>(this Nullable<T> self) where T : struct
    {
        return true;
    }
}

Использование Reflection и type.IsGeneric и type.GetGenericParameters() не работало с моим текущим набором .NET Runtimes.