难以定义可空性约束
我有一个名为 TryGetValueAs
的扩展函数,它基本上将 TryGetValue
与强制转换结合在一起。问题是我不断收到可空性警告,但我似乎无法正确处理。
我有以下代码:
using System.Diagnostics.CodeAnalysis;
public static class Extensions
{
public static bool TryGetValueAs<TOut, TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, [MaybeNullWhen(false)] out TOut value)
where TOut : TValue
{
if (dictionary.TryGetValue(key, out var v))
{
value = (TOut)v!;
return true;
}
else
{
value = default;
return false;
}
}
}
public interface IFoo {}
public class Foo : IFoo {}
class Program
{
public static void Main(string[] args)
{
var dict = new Dictionary<string, IFoo>();
if (dict.TryGetValueAs("foo", out Foo foo))
{
Console.WriteLine(foo.ToString());
}
}
}
我尝试将 out Foo foo
更改为 out Foo? foo
,但这只会导致更多警告。如何编写此函数,以便它正确处理可为空性,同时与值和引用兼容?
I have an extension function called TryGetValueAs
which basically combines TryGetValue
with a cast. The problem is that I keep getting nullability warnings and I can't seem to get it right.
I have the following code:
using System.Diagnostics.CodeAnalysis;
public static class Extensions
{
public static bool TryGetValueAs<TOut, TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, [MaybeNullWhen(false)] out TOut value)
where TOut : TValue
{
if (dictionary.TryGetValue(key, out var v))
{
value = (TOut)v!;
return true;
}
else
{
value = default;
return false;
}
}
}
public interface IFoo {}
public class Foo : IFoo {}
class Program
{
public static void Main(string[] args)
{
var dict = new Dictionary<string, IFoo>();
if (dict.TryGetValueAs("foo", out Foo foo))
{
Console.WriteLine(foo.ToString());
}
}
}
I tried changing out Foo foo
to out Foo? foo
, but that only results in more warnings. How can I write this function so that it correctly handles the nullability, while also being compatible with both values and references?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是我的尝试:
注意:
out TOut value
->出 TOut? value
- 这是必需的,因为此方法可以返回 null。[MaybeNullWhen(false)]
更改为[NotNullWhen(true)]
- 这告诉编译器TryGetValueAs
返回 true,然后foo< /code> 不为空。我认为这比
MaybeNullWhen
更好地代表了这个函数。当我使用 foo.GetType() 并且没有收到编译器警告时,我们可以看到此更改的好处;&& v 是 TOut
,用于处理所需类型与实际类型不匹配的情况。虽然这与这个问题的主题并不严格相关,但我认为这是一个大问题:Try
方法确实不应该抛出。让我们测试一下:
输出看起来不错:
Here is my attempt:
Notes:
out TOut value
->out TOut? value
- this is required because this method can return null.[MaybeNullWhen(false)]
to[NotNullWhen(true)]
- this tells the compiler thatTryGetValueAs
returns true thenfoo
is not null. I think this better represents this function thanMaybeNullWhen
. We can see the benefit of this change when I usefoo.GetType()
and don't get a complier warning;&& v is TOut
to handle the case when the desired and actual type don't match. While this is not strictly related to the topic of this question I think this a big one:Try
method really should not throw.Let's test it:
The output looks good:
如果我正确理解逻辑,那么使用
NotNullWhenAttribute
为true
返回值与TOut? value
参数应该可以解决问题:请注意,您可能不会执行类型测试,也不会直接进行强制转换,即使用类似以下内容的
value = (TOut)v!;
代替:If I understand the logic correctly then using
NotNullWhenAttribute
fortrue
return value withTOut? value
argument should do the trick:Note that probably you will won't to perform type test and not cast directly, i.e. instead of
value = (TOut)v!;
use something like :