C# Language
Неверные типы
Поиск…
Синтаксис
-
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));
}
}