zoukankan      html  css  js  c++  java
  • 可空类型

    值类型变量不能为null

    对于一个引用类型变量来说,其值是一个引用,而值类型是它的真实数据。
    一个非空引用值提供一个访问对象的途径,null相当于一个特殊的值。
    内存中用全零来表示null,清除一整块内存开销最低,所以对象选择用这种方式来初始化,本质上是和其他引用一样的方式来存储的。
    在C#1种表示空值的模式
    模式一:魔值
    选定一个值来表示空值。好处:不需浪费任何内存,不需添加任何类型。坏处:这个值永远不能表示真正的数据。
    ADO.NET中,所有类型空值都用魔值DBNull.Value来表示。
    模式二:引用类型包装
    有两种形式:
    一种:直接用object作为变量类型。
    另一种:假定值类型A可空,就为它准备一个引用类型B,在引用类型B中,包含值类型A的一个实例变量。
    都存在一个问题:虽然允许直接使用null,但都要求在堆上创建对象。
    模式三:额外的布尔标志
    使用一个普通类型的值类型的值,同时用另一个值来表示值的真正存在。
    System.Nullable<T>和System.Nullable
    可空类型的核心是System.Nullable<T>
    System.Nullable<T>简介
    Nullable<T>是一个泛型,类型参数T有一个值类型约束。T的类型是可空类型的基础类型
    Nullable<T>最重要部分是它的属性,HasValue和Value。它有两个构造函数,默认构造函数创建一个没有值的实例,另一个接受T的一个实例作为值,实例一经创建,就是不易变的。
    1. #region 4-1使用Nullable<T>的各个成员
    2. Nullable<int> x = 5;//包装等于5的值
    3. x = new Nullable<int>(5);
    4. Console.WriteLine("Instance with value:");
    5. Display(x);
    6. x = new Nullable<int>();//构造没有值的实例
    7. Console.WriteLine("Instance with value:");
    8. Display(x);
    9. #endregion
    1. #region 4-1
    2. static void Display(Nullable<int> x)//显示诊断结果
    3. {
    4. Console.WriteLine("HasValue:{0}", x.HasValue);// 如果当前的 System.Nullable<T> 对象具有值,则为 true;如果当前的 System.Nullable<T> 对象没有值,则为false。
    5. if (x.HasValue)//只有有值是才执行,避免异常
    6. {
    7. Console.WriteLine("Value:{0}", x.Value);//如果 System.Nullable<T>.HasValue 属性为 true,则为当前 System.Nullable<T> 对象的值。 如果System.Nullable<T>.HasValue 属性为 false,则将引发异常。
    8. Console.WriteLine("Explicit conversion:{0}", (int)x);//显示转换
    9. }
    10. Console.WriteLine("GetValueOrDefalt():{0}", x.GetValueOrDefault());// 如果 System.Nullable<T>.HasValue 属性为 true,则为 System.Nullable<T>.Value 属性的值;否则为当前System.Nullable<T> 对象的默认值。
    11. Console.WriteLine("GetValueOrDefalt(10):{0}", x.GetValueOrDefault(10));// 如果 System.Nullable<T>.HasValue 属性为 true,则为 System.Nullable<T>.Value 属性的值;否则为defaultValue 参数。
    12. Console.WriteLine("ToString():"{0}"", x.ToString());// 如果 System.Nullable<T>.HasValue 属性为 true,则是当前 System.Nullable<T> 对象的值的文本表示形式;如果System.Nullable<T>.HasValue 属性为 false,则是一个空字符串 ("")。
    13. Console.WriteLine("GetHashCode():"{0}"", x.GetHashCode());// 如果 System.Nullable<T>.HasValue 属性为 true,则为 System.Nullable<T>.Value 属性返回的对象的哈希代码;如果System.Nullable<T>.HasValue 属性为 false,则为零。
    14. Console.WriteLine();
    15. }
    16. #endregion
    Nullable<T>装箱和拆箱
    Nullable<T>是一个值类型,可以转换成引用类型。
    1. #region 4-2可空类型的装箱和拆箱行为
    2. Nullable<int> nullable = 5;
    3. object boxed = nullable;//装箱成“有值的可空类型实例”
    4. Console.WriteLine(boxed.GetType());
    5. int normal = (int)boxed;//拆箱成非可空变量
    6. Console.WriteLine(normal);
    7. nullable = (Nullable<int>)boxed;//拆箱成可控变量
    8. Console.WriteLine(nullable);
    9. nullable = new Nullable<int>();
    10. boxed = nullable;//装箱成没有值的可空类型实例
    11. Console.WriteLine(boxed == null);
    12. nullable = (Nullable<int>)boxed;//拆箱成可空变量
    13. Console.WriteLine(nullable.HasValue);
    14. #endregion
    Nullable<T>实例的相等性
    first.Equals(second)具体规则:
    • 如果first没有值,second为null,相等
    • 如果first没有值,second不为null,不相等
    • 如果first有值,second为null,不相等
    • first等于second,相等
    C#可空类型提供的语法糖
    ?修饰符
    1. #region 4-3使用?修饰符
    2. int? nullable = 5;
    3. object boxed = nullable;
    4. Console.WriteLine(boxed.GetType());
    5. int normal = (int)boxed;
    6. Console.WriteLine(normal);
    7. nullable = (int?)boxed;
    8. Console.WriteLine(nullable);
    9. nullable = new int?();
    10. boxed = nullable;
    11. Console.WriteLine(boxed == null);
    12. nullable = (int?)boxed;
    13. Console.WriteLine(nullable.HasValue);
    14. #endregion
    使用null进行赋值和比较
    C#编译器允许null在比较和赋值时表示可空类型的空值
    1. #region 4-4
    2. class Person
    3. {
    4. DateTime birth;
    5. DateTime? death;
    6. string name;
    7. public TimeSpan Age
    8. {
    9. get
    10. {
    11. if (death == null)//检查HasValue IL: if (!this.death.HasValue)
    12. {
    13. return DateTime.Now - birth;//IL: return (TimeSpan) (DateTime.Now - this.birth);
    14. }
    15. else
    16. {
    17. return death.Value - birth;//拆包进行计算 IL:return (this.death.Value - this.birth);
    18. }
    19. }
    20. }
    21. public Person(string name, DateTime birth, DateTime? death)
    22. {
    23. this.birth = birth;
    24. this.death = death;
    25. this.name = name;
    26. }
    27. }
    28. #endregion
    1. #region 4-4Person
    2. Person turing = new Person("Alan Turing", new DateTime(1912, 6, 23), new DateTime(1954, 6, 7));
    3. Person knuth = new Person("Donald Knuth", new DateTime(1938, 1, 10), null);
    4. Console.WriteLine("turing age:{0}", turing.Age.Days);
    5. Console.WriteLine("knuth age:{0}", knuth.Age);
    6. #endregion
    可空转换和操作符
    一个非空的值类型支持一个操作符或者一种转换,那个操作符或转换涉及其他非可空的值类型时,那么可空的值类型也支持相同的操作符或转换,通常将非可空的值类型转换成它们的可空等价物。
    可空逻辑bool?
    对可空类型使用as操作符
    结果:可空类型的某个值——空值(如果原始引用为错误类型或空)或有意义的值
    1. #region 对可空类型使用as
    2. PrintValueAsInt32(5);
    3. PrintValueAsInt32("some");
    4. #endregion
    1. #region 对可空类型使用as
    2. static void PrintValueAsInt32(object o)
    3. {
    4. int? nullable = o as int?;
    5. Console.WriteLine(nullable.HasValue ? nullable.ToString() : "null");
    6. Console.WriteLine(nullable.ToString());
    7. }
    8. #endregion
    空合并操作符??
    可用于值类型和引用类型
    结合性为右结合
    1. //使用可空操作符??
    2. public TimeSpan Age
    3. {
    4. get
    5. {
    6. return (death ?? DateTime.Now) - birth;
    7. }
    8. }
    可空类型的其他用法
    尝试一个不使用输出参数的操作
    用一个返回值来判断操作是否成功,并用一个输出参数来返回真正的结果。
    1. #region Tryxxx模式的备选实现 int?其他用法
    2. int? parsed = TryParse("12121");
    3. if (parsed != null)
    4. {
    5. Console.WriteLine("Parsed to {0}", parsed.Value);
    6. }
    7. else
    8. {
    9. Console.WriteLine("Couldn't parse");
    10. }
    11. #endregion
    1. #region 4-5
    2. static int? TryParse(string text)
    3. {
    4. int ret;
    5. if (int.TryParse(text, out ret))
    6. {
    7. return ret;
    8. }
    9. else
    10. {
    11. return null;
    12. }
    13. }
    14. #endregion
    空合并操作符用于比较
    1. #region 4-6 部分比较 int?使用方法
    2. public static class PartialComparer
    3. {
    4. public static int? Compare<T>(T first, T second)
    5. {
    6. return Compare(Comparer<T>.Default, first, second);
    7. }
    8. public static int? Compare<T>(Comparer<T> comparer, T first, T second)
    9. {
    10. int ret =comparer.Compare(first,second);
    11. return ret==0?new int?():ret;
    12. }
    13. public static int? ReferenceCompare<T>(T first, T second) where T : class
    14. {
    15. return first == second ? 0
    16. : first == null ? -1
    17. : second == null ? 1
    18. : new int?();
    19. }
    20. }
    21. #endregion
  • 相关阅读:
    去除 SQL Server 查询结果中的两边空格
    Ubuntu 中安装 Oracle 10g
    不同格式的下拉列表框
    闲来无趣,写了个简单的JavaScript验证码
    Ubuntu 任务前后台调度管理
    C#数据类型转换,Convert
    OleDbType,C#,access 对应数据类型,互相对应
    SQL 将查询出的表当做 value 插入到表中
    asp.net mvc && asp.net 页面跳转
    asp.net mvc 与 asp.net结合(asp.net mvc 技巧)
  • 原文地址:https://www.cnblogs.com/Tan-sir/p/5169203.html
Copyright © 2011-2022 走看看