对于'char'变量,'int'永远不会等于 null



有人能回答我这个-为什么我得到这个警告"表达式的结果总是'假',因为类型'int'的值永远不等于'null'类型'int?"

代码

    private char classLetter;
    public char ClassLetter
    {
        get { return classLetter; }
        set 
        {
            if (classLetter == null)
            {
                classLetter = value;
                RaisePropertyChanged("ClassLetter");
            }
            else throw new ArgumentOutOfRangeException();
        }
    }

如果我使用这段代码,没有警告出现

    private char classLetter;
    public char ClassLetter
    {
        get { return classLetter; }
        set 
        {
            if (classLetter.ToString() == null)
            {
                classLetter = value;
                RaisePropertyChanged("ClassLetter");
            }
            else throw new ArgumentOutOfRangeException();
        }
    }

总之,我的问题是

如何为char变量给出int警告?

编辑:'char'应该包含任何拉丁字母或西里尔字母,不允许有特殊符号和数字。如何过滤呢?

在第一种情况下,classLetter的类型是char,而CC_2不可能是null,因为它是一个值类型;它需要是char?型的。所以比较classLetter == null是没有意义的,因为编译器说。

在第二种情况下,想象classLetter'x'。当执行classLetter.ToString()时,您得到"x",它可以与null进行比较,因为它现在是引用类型。但是,这不是你想要的,因为classLetter.ToString()永远不会是null

如果你想只设置一次值,你可以这样做:

private char? classLetter = null; // make it nullable
public char ClassLetter
{
    get {
        if(classLetter == null) { // if we don't have a value yet
            // do something, like throwing an exception
        }else{ // if we do have a value already
            return classLetter.Value; // here we return char, not char?
        }
    }
    set 
    {
        if (classLetter == null) {
            classLetter = value;
            RaisePropertyChanged("ClassLetter");
        }
        else throw new ArgumentOutOfRangeException();
    }
}

类型为char的变量是值变量,而不是引用变量,因此它永远不可能是null。只有引用类型的变量可以是null

您将得到一个警告,因为值类型永远不会为空。完整的(er)解释如下。

c#中的char是一个值类型,永远不能为空。考虑char的目的,即表示一个Unicode字符。在0x0到0xFFFFFFFF范围内,没有一个合适的值来表示null。(的确,UTF-16实际上并没有涵盖整个范围,但将来可能会。)

对于一个范围小得多的东西来说,这有点容易理解。考虑byte。取值范围为0 - 255。现在,为了表示null,我们需要选择一种存储null的方式。最后出现了一些解决方案:

  • 将额外的信息存储到byte以表示null。
  • 在有效的byte范围内选择一个值来代替实际的null。您最终需要在整个程序中检查此值。在小范围内,这不是问题,但是当您不知道谁将使用您的代码时(很可能是这种情况),您必须记录并希望他们看到。

提供非空值类型和默认值是一个更简单的实现,如果需要,提供一个可以表示null的值类型的包装器,. net对Nullable<T>类型和语言支持的快捷方式(int?, byte?等)就是这样做的。

如果classLetter真的可以是char可以表示的任何值,那么您可以使用:

private char classLetter;
public char ClassLetter
{
    get { return classLetter; }
    set 
    {
        classLetter = value;
        RaisePropertyChanged("ClassLetter");
    }
}

你可以这样做,因为如果用户试图对classLetter做一些他们不可能做的事情,编译器会给用户一个编译时错误。

如果你对classLetter应该代表什么有额外的要求,更新你的问题,我将更新我的答案。

在回应你对另一个答案的评论时:"我希望行为简单。我希望能够放置任何符号,但我不希望变量为空"

我们需要解决的唯一一件事是"空"的真正含义。在你的语境中,空是什么意思?一旦回答了这个问题,就可以在包含classLetter的类型中使用默认初始化将其设置为该值。一个一般化的例子:

class Foo {
  private char classLetter;
  public char ClassLetter {
    get { return classLetter; }
    set {
      classLetter = value;
    }
  }
  public Foo(char classLetter = 'A') {
    this.ClassLetter = classLetter;
  }
}

当调用者使用new Foo()时,他们将得到一个Foo实例,其中Foo.ClassLetter == 'A'。当然,A可以是任何合理的默认值,以满足您的特定需求。

这是你想要的吗?

private char? classLetter;
public char ClassLetter
{
    get { return classLetter.Value; // this will throw exception, if value hasn't set }
    set 
    {
        if (classLetter != null)
        {
            throw new InvalidOperationException("ClassLetter has been set already.");
        }
        classLetter = value;
        RaisePropertyChanged("ClassLetter");
    }
}

注意,ArgumentOutOfRangeException不适合这种情况。没有对参数的范围进行任何测试。

最新更新