`
star65225692
  • 浏览: 277414 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类

C# 中的Nullable静态类

 
阅读更多

前段时间忙于各处奔波没有写博,今天想和大家再来看看一个奇妙的函数。

首先假设你不得不处理一些已有的代码,里面用到了nullable(可空值类型)的变量, 你必须要用这变量与不可空变量比较.
使用  <, >, <=, >= 来比较 nullable 值

看下面的代码:

1: int? x = null;
2: 
3: if (x < 100)
4: {
5:     Console.WriteLine("是, {0} 小于 100.",
6:                       x.HasValue ? x.ToString() : "null");
7: }
8: else欠款
9: {
0:     Console.WriteLine("否, {0} 不小于 100.",
1:                       x.HasValue ? x.ToString() : "null");
2: }

有人可能认为要么结果为“是”, 要么 抛出 NullReferenceException, 对吗? 因为一个null的整型在我们理解中是比100小,但是运行的结果为“否”!

 

下面的例子更加的令人费解,因为结果也为“否”:

1: int? x = null;
2: 
3: if (x < int.MaxValue)
4: {
5:     // ...
6: }

那么,我们说 null 小于所有的有效整型, 对吗? 如果对的话,你怎么看这段代码:

 1: int? x = null;
 2: 
 3: // 等等,X 不小于MinValue?
 4: if (x < int.MinValue)
 5: {
 6:     // ...
 7: }

如果我们使用大于符号判断时:

  1: int? x = null;
  2: 
  3: // x 也不大于MinValue….
  4: if (x > int.MinValue)
  5: {
  6:     // ...
  7: }

结果使用四种比较运算符 ( <, >, <=, >= ) 全都返回否。 这个同样适用于其他有这样运算符定义的类型: short,  float, double, DateTime, TimeSpan。

在.net 机制下 null 不是一个大数值,也不是小数值,比较时也不会发生异常。

 

更奇怪的事:

 1: DateTime? x = null;
 2: DateTime? y = null;
 3: 
 4: if (x <= y)
 5: {
 6:     Console.WriteLine("你觉得他们相等吗?");
 7: }
 8: else
 9: {
10:     Console.WriteLine("结果不是:<=, <, >, >= 根本不适用于null.");
11: }

再看看下面的代码:软件开发

  1: int? x = null;
  2: int? y = 100;
  3: 
  4: if (x < y)
  5: {
  6:     Console.WriteLine("X 小于 Y");
  7: }
  8: else if (x > y)
  9: {
 10:     Console.WriteLine("X 大于 Y");
 11: }
 12: else
 13: {
 14:     // 这个才是我们得到的结果
 15:     Console.WriteLine("X 等于 Y");
 16: }

。。
解决方案: nullable 静态类

因此,我们已经看到,<,<=,>,和>= 有一些有趣的意外行为。

但是,如果我们把null 看成是一个非常低的值应该怎么办?

例如,如果我们要排序一个列表。在列表中显示的是公司当前的股票价格:

 

代号      描述                                  价位
------      -----------------------    ----------
ABCZ        Apples and Oranges Inc     n/a
XYZP        Zippers and Buttons Inc    1.57
AZAZ        Carrots and Turnips Inc    23.13

 

比较运算符不适用于 null,因此,我们不得不做一些非常复杂的逻辑,如:

1: if (x.HasValue)
2: {
3:     if (y.HasValue)
4:     {
5:         if (x < y)
6:         {
7:             Console.WriteLine("x < y");
8:         }
9:         else if (x > y)
0:         {
1:             Console.WriteLine("x > y");
2:         }
3:         else
4:         {
5:             Console.WriteLine("x == y");
6:         }
7:     }
8:     else
9:     {
0:         Console.WriteLine("x > y 因为 y 是 null, x 不是");
1:     }
2: }
3: else if (y.HasValue)
4: {
5:     Console.WriteLine("x < y 因为 x 是 null, y 不是");
6: }
7: else
8: {
9:     Console.WriteLine("x == y 因为 都为 null");
0: }

 

我们也许可以简化这个函数,但它仍然是相当凌乱!但有一个更清洁的方式做到这一点,

如果你在MSDN上 读到 IComparer如何工作:

    当使用 IComparable 时,允许将 Nothing 与任何类型进行比较,而且不会生成异常。 排序时,Nothing 被视为小于任何其他对象。

所以,我们可以改变我们的逻辑使用Nullable.Compare <T>( )静态方法 :

1: int? x = null;
2: int? y = 100;
3: 
4: if (Nullable.Compare(x, y) < 0)
5: {
6:     //
7:     Console.WriteLine("x < y");
8: }
9: else if (Nullable.Compare(x, y) > 0)
0: {
1:     Console.WriteLine("x > y");
2: }
3: else
4: {
5:     Console.WriteLine("x == y");
6: }

摘要

所以,当比较两个数值而其中之一可能是一个null 时,考虑使用System.Nullable.Compare <T>( )方法,而不是比较运算符 。它会将 null 当作比任何值都小,而且使用它可以避免一些逻辑一致性问题,象 < 返回 false,>= 返回 true 等 。

分享到:
评论

相关推荐

    C#2.0.锐利体验系列课程(3):局部类型、空属类型、静态类

    锐利体验系列课程(3):局部类型、空属类型、静态类"中,我们将深入探讨C#编程语言的几个关键特性,这些特性极大地提升了代码的灵活性和效率。让我们逐一解析这些核心概念。 首先,我们要讨论的是**局部类型(Local ...

    C#2.0 锐利体验系列课程(3):局部类型、空属类型、静态类

    本课程重点讲解了三个关键概念:局部类型、空属类型(Nullable Types)以及静态类。下面我们将逐一深入探讨这些主题。 1. **局部类型(Local Types)** 局部类型是指在方法、块或控制流结构内声明的变量类型。在C#...

    C#1.0 C#1.2 C#2.0 C#3.0 语言规范全集(中文)

    1. **扩展方法**:使静态类能够向现有类型添加方法。 2. **匿名类型增强**:支持匿名类型自动推断字段名。 3. **Lambda表达式**:简洁地表示函数或委托,常用于LINQ查询。 4. **查询表达式**:引入新的查询语法,...

    C#2.0.锐利体验系列课程(3)

    最后,静态类是C#中的一个重要概念。静态类是一种不能实例化的类,它只能包含静态成员,如静态字段、静态方法和静态属性。这意味着不能通过"new"关键字来创建静态类的对象。静态类常用于提供工具方法或全局常量,...

    C#4.0语言规范 C#4.0语言规范C#4.0语言规范

    7. **扩展方法**:扩展方法允许在不修改原有类的情况下向其添加新方法,通过`this`关键字在静态类中定义。这为类库提供了优雅的扩展点,而不会破坏原有的类结构。 8. **异步编程模型**(Task Parallel Library, TPL...

    C#2.0锐利体验

    《C#2.0 锐利体验》是一套深度探讨C#编程语言特性的课程,主要聚焦于C#2.0版本的新特性及其在实际开发中的应用。通过以下几个主题,我们将深入理解C#2.0如何提升编程效率和代码质量。 1. **泛型编程**(C#2.0.锐利...

    C# 2.0.ppt

    5. 静态类(Static Classes):静态类是不能实例化的类,它们只能包含静态成员,为全局工具类和单例模式提供了方便。 6. 属性访问的保护级别(Accessor Accessibility):C# 2.0允许开发者分别设置属性的get和set...

    深入理解C#2.0版

    虽然嵌套类在C# 1.0中就已经存在,但在C# 2.0中对它们进行了改进,特别是通过使用`static`修饰符支持静态嵌套类。这使得可以在不实例化外部类的情况下访问静态嵌套类,从而提高了灵活性。 ### 5. 属性(Properties...

    C# 语言规范 2.0

    4. 静态类和静态构造函数:C# 2.0引入了静态类,这种类不能实例化,只能包含静态成员。静态构造函数是在类第一次被引用时执行的,用于初始化静态数据。 5. yield关键字:yield关键字与迭代器配合使用,可以在运行时...

    C# Language Specification 2.0.pdf

    5. **方法、构造器与析构函数**:方法是C#中的行为单元,包括普通方法、静态方法、抽象方法、重载方法等。构造器用于初始化类的新实例,而析构函数则在对象即将被垃圾回收时执行,释放非托管资源。 6. **泛型**:C#...

    C# 果壳 最新版本 英字 PDF.zip

    1. **非空引用类型(Nullable Reference Types)**:这是C# 8.0的一个主要特性,它允许开发者明确指定引用类型变量是否可以为null,从而减少因意外的null引用异常导致的错误。 2. **异步流(Async Streams)**:在C# ...

    c#2.0新特性(修订)

    5. **属性和字段初始化器**:在C# 2.0中,可以在类的实例或静态字段声明中直接进行初始化,简化了对象的构造过程。 6. **自动属性(Auto-Implemented Properties)**:自动属性提供了更简洁的语法来声明和实现只读...

    c#一些常用实用技巧

    定义在静态类中的扩展方法必须有一个接收`this`修饰的参数,这个参数是你要扩展的类型。例如,为字符串类添加去除空白的方法: ```csharp public static class StringExtensions { public static string ...

    C#.NET编程新语言

    5. 静态类和静态构造函数:静态类不能实例化,所有成员都是静态的,而静态构造函数用于初始化静态数据。 四、高级特性 1. async/await:C# 5.0引入的异步编程模型,简化了非阻塞I/O操作的编写。 2. 值类型和引用...

    通用函数库c#语言

    这个文件中可能定义了一个名为`SystemHelps`的类,封装了各种通用的静态方法,如获取IP、文件操作、加密解密和变量处理等。使用时,只需引入这个类库,就可以方便地调用其中的方法,简化代码编写。 通过创建和使用...

    C#2.0宝典源码文件

    7. **Static Class(静态类)**:C# 2.0允许整个类声明为静态,这意味着类不能被实例化,所有成员都是静态的,节省内存资源。 8. **Checked and Unchecked(检查溢出和不检查溢出)**:这两个关键字用于控制整数...

    C#高效编程改进C#代码的50个行之有效的办法( 第2版) 中文版

    以上这些知识点是《C#高效编程改进C#代码的50个行之有效的办法(第2版)》中的核心内容,它们涵盖了C#语言的各个方面,旨在帮助开发者编写更高效、更易维护的代码。通过学习和实践这些技巧,你的C#编程技能将得到显著...

    极客学院 C#4-1 高阶特性

    通过`this`关键字定义,通常放在静态类中。这提高了代码的可复用性和灵活性,例如LINQ中的许多操作就利用了扩展方法。 4. **匿名类型(Anonymous Types)** 匿名类型用于临时存储数据,无需显式声明类型名称。在...

Global site tag (gtag.js) - Google Analytics