有人可以回答我这个问题 - 为什么我会收到这个警告“表达式的结果总是'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'应该包含任何拉丁语或西里尔字母,没有特殊符号,也不允许使用数字。该如何过滤?
答案 0 :(得分:4)
类型char
的变量是值变量,而不是引用变量,因此它永远不会是null
。只有参考类型的变量可以是null
。
答案 1 :(得分:4)
在第一种情况下,classLetter
属于char
类型,永远不会是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();
}
}
答案 2 :(得分:1)
您收到警告,因为值类型永远不会为null。完整(呃)解释如下。
C#中的char
是值类型,永远不能为空。考虑char
的目的,即表示Unicode字符。在0x0到0xFFFFFFFF范围内选择平均值null
并没有什么好处。 (确实,UTF-16实际上并不包含整个范围,但它可能会在某一天)。
使用范围小得多的东西有点容易理解。考虑byte
。它的范围为0 - 255.现在,为了表示null
,我们需要选择一种可以存储null
的方式。最终会出现一些解决方案:
byte
以表示null。 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
可以是满足您特定要求的任何合理默认值。
答案 3 :(得分:0)
这是你想要的吗?
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
不适合这种情况。您不对参数的范围进行任何测试。