可空引用类型和 ToString() 重载
Nullable references types and ToString() overload
请注意,此问题是关于最新的 C# 8 nullable-references,我已通过以下 <Nullable>enable</Nullable>
声明在 csproj
文件中启用它。
考虑以下简单代码
class SortedList<T> where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
{
private Node? _node;
private readonly IComparer<T> _comparer = Comparer<T>.Default;
class Node
{
public Node(T value)
{
Value = value;
}
public T Value { get; }
public Node? Next { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
//rest of code, that isn't important
}
行 return Value.ToString();
给我一个 CS8603 Possible null reference return 警告和我的问题实际上为什么它在这里?
我正在使用 where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
泛型约束来匹配数字类型,Value
实际上是值类型,而不是引用类型。也没有 ToString()
对任何值类型的重载,默认的 implementation for Int32
(for example) returns non-nullable string
. MSDN notes to inheritors 也表示
Your ToString()
override should not return Empty
or a null
string.
编译器是否抱怨某些类型可以满足泛型约束和来自 ToString()
的 return null
?
我可以通过使 return 类型为 nullable
来避免警告
public override string? ToString()
{
return Value.ToString();
}
或使用空合并运算符
public override string ToString()
{
return Value.ToString() ?? "";
}
或通过 null-forgiving 运算符
public override string ToString()
{
return Value.ToString()!;
}
但这些选项大多看起来像是一个把戏,我正在寻找对这种行为的解释,为什么会出现这种情况,是设计使然还是其他任何原因?除上述方法外,还有其他方法可以避免警告吗?
顺便说一句,这个选项不起作用,警告仍然存在
[return: MaybeNull]
public override string ToString()
{
return Value.ToString();
}
我正在使用 .NET Core 3.1 和 VS 2019 16.4.2,但我认为这在这里并不重要。
在此先感谢您的帮助!
object.ToString()
的签名是:
public virtual string? ToString()
也就是说,对象的 ToString()
方法被定义为 returning 一个可能为空的字符串。
您对 Node.ToString()
的重载收紧了此要求并承诺 return 一个非空字符串。这可以。例如,Int32
会这样做(如您所述)。
但是,您的 Node.ToString()
方法 return 是 Value.ToString()
的值。我们刚刚看到这个 ToString
方法(即 object.ToString()
)可能 return null
。因此,编译器警告您,您的 Node.ToString()
方法可能会无意中 return null
,如果 Value.ToString()
returns null
.
这解释了为什么您发现将 Node.ToString()
声明为:
public override string? ToString()
抑制了警告:您现在声明您的 Node.ToString()
方法可能 return null
,因此 Value.ToString()
return 不是问题s null
然后你 return 这个值。
它还解释了为什么写 return Value.ToString() ?? "";
会抑制警告:如果 Value.ToString()
returned null
,该代码将确保 Node.ToString()
没有 return null
.
如何最好地解决这个问题?你来决定。
您想要保证您的Node.ToString()
方法永远不会returnnull
吗?如果是这样,您需要弄清楚如果 Value.ToString()
returns null
.
该怎么办
否则,最好遵循既定模式,并说您的 Node.ToString()
方法可能 return null
.
为什么会object.ToString()
returnstring?
?有关完整讨论,请参阅 this thread,但要点是在野外有 ToString
方法 do return null
,因为有些人不遵循您永远不应该 return null
或空字符串的准则。
- 如果您引用的类型是在没有可为空注释的情况下构建的,那么
object.ToString()
returns string?
意味着您将收到警告,除非您检查null
。这可以保护您免受编写错误的 ToString
方法的影响。
- 如果您引用的类型是 使用 可空注释构建的,则:
- 作者遵循了指南,并将他们的
ToString
方法声明为 returning string
。在这种情况下,编译器假定您不会得到 null
.
- 作者明确没有遵循指南,并将他们的
ToString
方法声明为 returning string?
。在这种情况下,您必须检查 null
.
请注意,当您在 Visual Studio 中创建 ToString
的重载时,生成的方法 returns string
(即使方法被重载 returns string?
)。这会提示您遵循指南。
这里唯一的烦恼是当您处理泛型类型或已强制转换为 object
的类型时。在这种情况下,编译器不知道对象的 ToString
方法是否遵循准则。因为 object.ToString
returns string?
,编译器假设了最坏的情况。如果您愿意,可以使用 null-forgiving 运算符 !
.
来覆盖此假设
请注意,此问题是关于最新的 C# 8 nullable-references,我已通过以下 <Nullable>enable</Nullable>
声明在 csproj
文件中启用它。
考虑以下简单代码
class SortedList<T> where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
{
private Node? _node;
private readonly IComparer<T> _comparer = Comparer<T>.Default;
class Node
{
public Node(T value)
{
Value = value;
}
public T Value { get; }
public Node? Next { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
//rest of code, that isn't important
}
行 return Value.ToString();
给我一个 CS8603 Possible null reference return 警告和我的问题实际上为什么它在这里?
我正在使用 where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
泛型约束来匹配数字类型,Value
实际上是值类型,而不是引用类型。也没有 ToString()
对任何值类型的重载,默认的 implementation for Int32
(for example) returns non-nullable string
. MSDN notes to inheritors 也表示
Your
ToString()
override should not returnEmpty
or anull
string.
编译器是否抱怨某些类型可以满足泛型约束和来自 ToString()
的 return null
?
我可以通过使 return 类型为 nullable
来避免警告public override string? ToString()
{
return Value.ToString();
}
或使用空合并运算符
public override string ToString()
{
return Value.ToString() ?? "";
}
或通过 null-forgiving 运算符
public override string ToString()
{
return Value.ToString()!;
}
但这些选项大多看起来像是一个把戏,我正在寻找对这种行为的解释,为什么会出现这种情况,是设计使然还是其他任何原因?除上述方法外,还有其他方法可以避免警告吗?
顺便说一句,这个选项不起作用,警告仍然存在
[return: MaybeNull]
public override string ToString()
{
return Value.ToString();
}
我正在使用 .NET Core 3.1 和 VS 2019 16.4.2,但我认为这在这里并不重要。 在此先感谢您的帮助!
object.ToString()
的签名是:
public virtual string? ToString()
也就是说,对象的 ToString()
方法被定义为 returning 一个可能为空的字符串。
您对 Node.ToString()
的重载收紧了此要求并承诺 return 一个非空字符串。这可以。例如,Int32
会这样做(如您所述)。
但是,您的 Node.ToString()
方法 return 是 Value.ToString()
的值。我们刚刚看到这个 ToString
方法(即 object.ToString()
)可能 return null
。因此,编译器警告您,您的 Node.ToString()
方法可能会无意中 return null
,如果 Value.ToString()
returns null
.
这解释了为什么您发现将 Node.ToString()
声明为:
public override string? ToString()
抑制了警告:您现在声明您的 Node.ToString()
方法可能 return null
,因此 Value.ToString()
return 不是问题s null
然后你 return 这个值。
它还解释了为什么写 return Value.ToString() ?? "";
会抑制警告:如果 Value.ToString()
returned null
,该代码将确保 Node.ToString()
没有 return null
.
如何最好地解决这个问题?你来决定。
您想要保证您的Node.ToString()
方法永远不会returnnull
吗?如果是这样,您需要弄清楚如果 Value.ToString()
returns null
.
否则,最好遵循既定模式,并说您的 Node.ToString()
方法可能 return null
.
为什么会object.ToString()
returnstring?
?有关完整讨论,请参阅 this thread,但要点是在野外有 ToString
方法 do return null
,因为有些人不遵循您永远不应该 return null
或空字符串的准则。
- 如果您引用的类型是在没有可为空注释的情况下构建的,那么
object.ToString()
returnsstring?
意味着您将收到警告,除非您检查null
。这可以保护您免受编写错误的ToString
方法的影响。 - 如果您引用的类型是 使用 可空注释构建的,则:
- 作者遵循了指南,并将他们的
ToString
方法声明为 returningstring
。在这种情况下,编译器假定您不会得到null
. - 作者明确没有遵循指南,并将他们的
ToString
方法声明为 returningstring?
。在这种情况下,您必须检查null
.
- 作者遵循了指南,并将他们的
请注意,当您在 Visual Studio 中创建 ToString
的重载时,生成的方法 returns string
(即使方法被重载 returns string?
)。这会提示您遵循指南。
这里唯一的烦恼是当您处理泛型类型或已强制转换为 object
的类型时。在这种情况下,编译器不知道对象的 ToString
方法是否遵循准则。因为 object.ToString
returns string?
,编译器假设了最坏的情况。如果您愿意,可以使用 null-forgiving 运算符 !
.