【问题标题】:'int' never equal to null for 'char' variables对于 'char' 变量,'int' 从不等于 null
【发布时间】:2014-03-10 17:13:30
【问题描述】:

有人可以回答我吗 - 为什么我会收到此警告“表达式的结果始终为 'false',因为 'int' 类型的值永远不会等于 'int' 类型的 'null'?”

这里是代码

    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 == null 会是真的吗? classLetter 的值是多少?
  • 你想写setter,它只允许设置一次属性吗?另外,你为什么不使用char?,如果你想测试,那个属性是设置过的?
  • @usr 好吧,假设我没有在与该字段相对应的文本框中输入任何内容-然后该字段为空。据我所知,这会导致一个空变量。如果我错了,请纠正我
  • @Dennis 我认为 char 是可以为空的类型,所以我没有看到使它可以为空的逻辑
  • 如果您真的希望它为空,请使用“char?”而不是“字符”。另请阅读... msdn.microsoft.com/en-us/library/x9h8tsay.aspx

标签: c# variables char int compiler-warnings


【解决方案1】:

在第一种情况下,classLetterchar 类型,它永远不可能是 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 不是可空类型,因此必须设为可空。感谢您的快速回复。
  • @GeorgeAnastasov 很高兴为您提供帮助
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    您会收到警告,因为值类型永远不会为空。完整(呃)解释如下。

    C# 中的char 是一种值类型,并且永远不能为空。考虑char 的用途,即表示一个Unicode 字符。在 0x0 到 0xFFFFFFFF 范围内选择表示 null 并不是一个很好的值。 (确实,UTF-16 实际上并没有涵盖整个范围,但有一天它可能会)。

    使用范围小得多的东西有点容易理解。考虑byte。它的范围是 0 - 255。现在,为了表示 null,我们需要选择一种可以存储 null 的方式。最终出现了一些解决方案:

    • 将额外信息存储到byte 以表示空值。 Nullable<Byte> 这样做。
    • 在有效的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 可以是任何符合您特定要求的合理默认值。

    【讨论】:

    • 我有一个问题 - 如果用户不输入任何内容会发生什么,那么 'char' 变量的值是什么
    • 不可能char 设置为空(或null)。 char 将设置为 '\0',即空终止字符。不要让 null 一词在这里让您感到困惑 - 它只是一个表示字符串结尾的字符,并且恰好是 char 要初始化为的合理默认值。
    【解决方案4】:

    这是你想要的吗?

    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 不适合这种情况。您不会对参数的 range 进行任何测试。

    【讨论】:

    • 我是否需要声明两个 char 变量都可以为空,或者只有私有变量就足够了。而且我不希望该值只设置一次,所以为什么要更改 if(..) 语句
    • @GeorgeAnastasov:你混淆了私有字段、属性和变量吗?这是字段:private char? classLetter。这是财产:public char ClassLetter。要回答有关if 的问题,您必须澄清您的财产的逻辑。它应该如何表现?您的 setter 只允许设置一次属性。
    • 我希望行为简单。我希望能够放置任何符号,但我不希望变量留空
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多