什么是值类型后面的问号(例如:int? myVariable)的目的?

565

通常问号的主要用途是条件运算符,例如x ? "yes" : "no"

但我看到过另一种使用方式,但找不到关于这种使用问号运算符?的解释,例如。

public int? myProperty
{
   get;
   set;
}

3
有一个关于“引用类型”的对应问题 - https://dev59.com/MlEG5IYBdhLWcg3wQIGq - Alexei Levenkov
1
它指的是值类型(这里是int?)是可空类型。 - AHAMED AAQIB
9个回答

548

这意味着问题中的值类型是 可空类型

可空类型是 System.Nullable 结构体的实例。可空类型可以表示其基础值类型的正确值范围,以及一个额外的 null 值。例如,Nullable<Int32>,发音为“Int32 的可空类型”,可以被赋予从 -2147483648 到 2147483647 的任何值,或者它可以被赋予 null 值。Nullable<bool> 可以被赋予 true、false 或 null 值。当你处理数据库和其他包含可能不被赋值的元素的数据类型时,将 null 赋给数字和布尔类型特别有用。例如,数据库中的布尔字段可以存储 true 或 false 值,或者它可能未定义。

class NullableExample
{
  static void Main()
  {
      int? num = null;

      // Is the HasValue property true?
      if (num.HasValue)
      {
          System.Console.WriteLine("num = " + num.Value);
      }
      else
      {
          System.Console.WriteLine("num = Null");
      }

      // y is set to zero
      int y = num.GetValueOrDefault();

      // num.Value throws an InvalidOperationException if num.HasValue is false
      try
      {
          y = num.Value;
      }
      catch (System.InvalidOperationException e)
      {
          System.Console.WriteLine(e.Message);
      }
  }
}

3
仅用于结构体。不认为对类有实际用处。 - MonsieurDart
11
@MonsieurDart- 这就是答案为什么说“值类型”的原因。 - Sean
3
@AntoineDahan - 值类型由定义上就是不可为空,因此它们没有可为空的类型。我想你可能在考虑Java,例如有int类型和相应的Integer类。 - Sean
2
可空类型的更多最新(2015)文档请参阅此处 - dinosaur
3
请注意,在C# 6(VS 2015)中,对象(类型的实例)后面可以跟随一个问号(?)。(参考链接:http://www.kunal-chowdhury.com/2014/12/csharp-6-null-conditional-operators.html#t6MtXHTTG6yPywQp.97) - Carol Skelly
显示剩余3条评论

150

3
第二句话让我感到困惑。你说的“cannot”是指编译器层面还是应用程序上下文? - problemofficer - n.f. Monica
6
根据定义,值类型不能为null。如果您声明一个int或bool(它们是值类型),而没有明确赋值,则它们仍然会有值(分别为0和false),即它们不会为null。相反,未分配的引用类型,例如object或MyClass,将为null。您可能想了解一下值类型和引用类型之间的区别。 - Klaus Byskov Pedersen

68

In

x ? "yes" : "no"
?声明一个if语句。这里:x表示布尔条件;在之前的部分是then语句,在之后的部分是else语句。

例如,


int?

?声明了一个可空类型,表示它之前的类型可能有一个空值。


13
先生,我没有看到'?'声明可空类型和三元表达式之间有任何关系。我会将您的答案投下去。 - Gus Crawford
49
我不同意上面Gus的评论。问题显示可能存在对三元表达式的困惑。这个答案解决了这个问题。 - Mario Levesque
你会在哪里使用这种空值比较?在返回语句中似乎不被允许。return value ? value : "isNull"; 告诉我 string value 无法转换为布尔类型。 - C4d
1
我必须说,与其他回答相比,这是一个非常复杂的答案。-1 - FastTrack
2
该问题陈述并不是关于“x?”和“yes”:“no”的问题,而是关于在类型声明后使用问号的时候。在我看来,这是一个非常糟糕的答案。 - BerggreenDK

17
它声明了该类型是可为空的,你可以在不提供任何值的情况下使用它。

7

实际应用:

public string someFunctionThatMayBeCalledWithNullAndReturnsString(int? value)
{
  if (value == null)
  {
    return "bad value";
  }

  return someFunctionThatHandlesIntAndReturnsString(value);
}

6

int?Nullable<int>的简写,两种形式可以互换使用。

Nullable<T>是一个操作符,你可以用它来使值类型T接受null

如果你不知道,值类型是指接受像intboolchar等值作为输入的类型...

它们不能接受值的引用:如果你给它们赋值null,会在编译时产生错误,而引用类型则可以接受它。

为什么需要这个呢? 因为有时候你的值类型变量可能会接收到一些不太好的返回值,比如从数据库返回的缺失或未定义的变量。

我建议你阅读Microsoft文档,因为它很好地涵盖了这个主题。


如果这两种形式是可以互换的,那么为什么其中一种会在编译时出现错误而另一种不会呢?比较public Item? item { get; set; };public Nullable<Item> item { get; set; };,其中Item是一个简单的类。 - Mattias Martens
1
@MattiasMartens Item 必须是一个值类型(结构体)- 类是引用类型。可空引用类型是完全不同的东西,不幸的是,它们具有相同的语法,这会导致一些混淆。 - Iain

6

使用(int?)声明的变量表示它是可空的。

int i1=1; //ok
int i2=null; //not ok

int? i3=1; //ok
int? i4=null; //ok

3
补充其他答案:
从C# 8.0开始,Nullable<>?并不总是可以互换使用。 Nullable<>仅适用于值类型,而?适用于引用类型和值类型
这些可以在文档中看到。

"可空引用类型的表示方式与可空值类型相同:在变量类型后附加一个?。"

以及此处

public struct Nullable<T> where T : struct


1
为了补充以上答案,这里提供一份代码示例。
struct Test
{
    int something;
}
struct NullableTest
{
    int something;
}
class Example
{
    public void Demo()
    {
        Test t = new Test();
        t = null;

        NullableTest? t2 = new NullableTest();
        t2 = null;
    }
}

这段代码会产生编译错误:

错误 12:无法将 null 转换为 'Test',因为它是一个非可空值类型。

需要注意的是,在NullableTest中没有编译错误。(注意t2声明中的问号?)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接