Обнаружение Обнуляемого Типа через отражение - PullRequest
22 голосов
/ 17 мая 2011

Удивительно, но следующий код не проходит утверждение:

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

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

Ответы [ 5 ]

50 голосов
/ 17 мая 2011

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

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

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

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

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

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

3 голосов
/ 11 ноября 2016

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

, упрощающее расширение для работы с любым типом, который нам подходит.но иногда ...:)

3 голосов
/ 14 февраля 2014
int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
    type.GetGenericTypeDefinition() == typeof(Nullable<>);
0 голосов
/ 25 августа 2016

Вот то, что я придумал, так как все остальное казалось неудачным - по крайней мере на Portable Class Library / DotNet Core с> = C # 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 Runtime.

0 голосов
/ 17 мая 2011

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

Следующие значения возвращаются true, как и следовало ожидать:

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...