Поиск…


Синтаксис

  • Nullable<int> i = 10;
  • Int? j = 11;
  • Int? k = null;
  • DateTime? DateOfBirth = DateTime.Now;
  • десятичный? Сумма = 1,0 м;
  • BOOL? IsAvailable = true;
  • обугливается? Letter = 'a';
  • (тип)? имяПеременной

замечания

Nullable типы могут представлять все значения базового типа, а также null .

Синтаксис T? является сокращением для Nullable<T>

Нулевыми значениями являются объекты System.ValueType , поэтому они могут быть в коробке и распакованы. Кроме того, null значение объекта с null значением не совпадает с null значением ссылочного объекта, это всего лишь флаг.

При боксировании с нулевым объектом нулевое значение преобразуется в null ссылку, а значение, отличное от null , преобразуется в базовый тип с нулевым значением.

DateTime? dt = null;
var o = (object)dt;
var result = (o == null); // is true

DateTime? dt = new DateTime(2015, 12, 11);
var o = (object)dt;
var dt2 = (DateTime)dt; // correct cause o contains DateTime value

Второе правило приводит к правильному, но парадоксальному коду:

DateTime? dt = new DateTime(2015, 12, 11);
var o = (object)dt;
var type = o.GetType(); // is DateTime, not Nullable<DateTime>

В краткой форме:

DateTime? dt = new DateTime(2015, 12, 11);
var type = dt.GetType(); // is DateTime, not Nullable<DateTime>

Инициализация нулевой

Для null значений:

Nullable<int> i = null;

Или же:

int? i = null;

Или же:

var i = (int?)null;

Для непустых значений:

Nullable<int> i = 0;

Или же:

int? i = 0;

Проверьте, имеет ли значение Nullable значение

int? i = null;

if (i != null)
{
    Console.WriteLine("i is not null");
}
else
{
    Console.WriteLine("i is null");
}

Это то же самое, что:

if (i.HasValue)
{
    Console.WriteLine("i is not null");
}
else
{
    Console.WriteLine("i is null");
}

Получить значение типа NULL

Учитывая следующее значение nullable int

int? i = 10;

В случае, если значение по умолчанию необходимо, вы можете назначить его с помощью оператора нулевой коалесценции , метода GetValueOrDefault или проверить, является ли HasValue int HasValue перед назначением.

int j = i ?? 0;
int j = i.GetValueOrDefault(0);
int j = i.HasValue ? i.Value : 0;

Следующее использование всегда небезопасно . Если i равно нулю во время выполнения, будет System.InvalidOperationException . Во время разработки, если значение не задано, вы получите сообщение Use of unassigned local variable 'i' ошибке Use of unassigned local variable 'i' .

int j = i.Value;

Получение значения по умолчанию из значения NULL

Метод .GetValueOrDefault() возвращает значение, даже если свойство .HasValue является ложным (в отличие от свойства Value, которое генерирует исключение).

class Program
{
    static void Main()
    {
        int? nullableExample = null;
        int result = nullableExample.GetValueOrDefault();
        Console.WriteLine(result); // will output the default value for int - 0
        int secondResult = nullableExample.GetValueOrDefault(1);
        Console.WriteLine(secondResult) // will output our specified default - 1
        int thirdResult = nullableExample ?? 1;
        Console.WriteLine(secondResult) // same as the GetValueOrDefault but a bit shorter
    }
}

Выход:

0
1

Проверьте, является ли типовой параметр типа NULL

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

Значение по умолчанию для типов с нулевым значением равно null

public class NullableTypesExample
{
    static int? _testValue;

    public static void Main()
    {
        if(_testValue == null)
            Console.WriteLine("null");
        else
            Console.WriteLine(_testValue.ToString());
    }
}

Выход:

ноль

Эффективное использование базового Nullable аргумент

Любой тип с нулевым значением является общим типом. И любой тип с нулевым значением - тип значения .

Существуют некоторые трюки, которые позволяют эффективно использовать результат метода Nullable.GetUnderlyingType при создании кода, связанного с целью отражения / генерации кода:

public static class TypesHelper {
    public static bool IsNullable(this Type type) {
        Type underlyingType;
        return IsNullable(type, out underlyingType);
    }
    public static bool IsNullable(this Type type, out Type underlyingType) {
        underlyingType = Nullable.GetUnderlyingType(type);
        return underlyingType != null;
    }
    public static Type GetNullable(Type type) {
        Type underlyingType;
        return IsNullable(type, out underlyingType) ? type : NullableTypesCache.Get(type);
    }
    public static bool IsExactOrNullable(this Type type, Func<Type, bool> predicate) {
        Type underlyingType;
        if(IsNullable(type, out underlyingType))
            return IsExactOrNullable(underlyingType, predicate);
        return predicate(type);
    }
    public static bool IsExactOrNullable<T>(this Type type)
        where T : struct {
        return IsExactOrNullable(type, t => Equals(t, typeof(T)));
    }
}

Использование:

Type type = typeof(int).GetNullable();
Console.WriteLine(type.ToString());

if(type.IsNullable())
    Console.WriteLine("Type is nullable.");
Type underlyingType;
if(type.IsNullable(out underlyingType))
    Console.WriteLine("The underlying type is " + underlyingType.Name + ".");
if(type.IsExactOrNullable<int>())
    Console.WriteLine("Type is either exact or nullable Int32.");
if(!type.IsExactOrNullable(t => t.IsEnum))
    Console.WriteLine("Type is neither exact nor nullable enum.");

Выход:

System.Nullable`1[System.Int32]
Type is nullable.
The underlying type is Int32.
Type is either exact or nullable Int32.
Type is neither exact nor nullable enum.

PS. NullableTypesCache определяется следующим образом:

static class NullableTypesCache {
    readonly static ConcurrentDictionary<Type, Type> cache = new ConcurrentDictionary<Type, Type>();
    static NullableTypesCache() {
        cache.TryAdd(typeof(byte), typeof(Nullable<byte>));
        cache.TryAdd(typeof(short), typeof(Nullable<short>));
        cache.TryAdd(typeof(int), typeof(Nullable<int>));
        cache.TryAdd(typeof(long), typeof(Nullable<long>));
        cache.TryAdd(typeof(float), typeof(Nullable<float>));
        cache.TryAdd(typeof(double), typeof(Nullable<double>));
        cache.TryAdd(typeof(decimal), typeof(Nullable<decimal>));
        cache.TryAdd(typeof(sbyte), typeof(Nullable<sbyte>));
        cache.TryAdd(typeof(ushort), typeof(Nullable<ushort>));
        cache.TryAdd(typeof(uint), typeof(Nullable<uint>));
        cache.TryAdd(typeof(ulong), typeof(Nullable<ulong>));
        //... 
    }
    readonly static Type NullableBase = typeof(Nullable<>);
    internal static Type Get(Type type) {
        // Try to avoid the expensive MakeGenericType method call
        return cache.GetOrAdd(type, t => NullableBase.MakeGenericType(t)); 
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow