Joe*_*Joe 2 c# c#-8.0 nullable-reference-types
我在 C# 8.0 项目中启用了可空引用。我还将所有警告设置为错误,以迫使自己解决所有此类警告。但其中之一让我感到困惑。它是一个依赖属性,它返回一个可能有效为空的接口指针。这是属性(在名为“LayerView”的控件内)
private static readonly DependencyProperty ShapeBeingDrawnProperty = DependencyProperty.Register(
nameof(ShapeBeingDrawn),
typeof(IShape),
typeof(LayerView),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
public IShape ShapeBeingDrawn
{
get => GetValue(ShapeBeingDrawnProperty) as IShape; // RIGHT SIDE OF "=>" UNDERLINED IN RED
set => SetValue(ShapeBeingDrawnProperty, value);
}
Run Code Online (Sandbox Code Playgroud)
启用可为空引用时,这会导致对 getter 的警告是可以理解的。get 的整个右侧用红色下划线标出,我收到此构建错误
1>C:\Users\jmole\Documents\Dev\Mobile\Core\Views\LayerView.xaml.cs(429,13,429,16): error CS8766:
Nullability of reference types in return type of 'IShape? LayerView.ShapeBeingDrawn.get' doesn't
match implicitly implemented member 'IShape ILayerView.ShapeBeingDrawn.get' (possibly because of
nullability attributes).
Run Code Online (Sandbox Code Playgroud)
首先,他们在谈论什么“隐式”实现的成员?这是一个显式实现的成员。我真的在这里实施它。但除此之外,我试图解决这个问题,因为我已经修复了许多其他此类有效可为空的属性:使属性返回一个可为空的引用
public IShape? ShapeBeingDrawn // ONLY CHANGE IS HERE
{
get => GetValue(ShapeBeingDrawnProperty) as IShape; // NOW, JUST "get" IS UNDERLINED IN RED
set => SetValue(ShapeBeingDrawnProperty, value);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这无济于事。我仍然遇到同样的错误,但这次唯一以红色下划线的部分只是 getter 的左侧(“get”一词)。
最后,我能够通过将属性更改回正常引用并在 getter 中使用硬转换来消除此错误
public IShape ShapeBeingDrawn
{
get => (IShape)GetValue(ShapeBeingDrawnProperty);
set => SetValue(ShapeBeingDrawnProperty, value);
}
Run Code Online (Sandbox Code Playgroud)
但是现在,任何试图将此属性设置为 null(有效)的代码都会出现编译器错误,我必须解决这个问题。
private void LayerView_OnKeyDown(object sender, KeyEventArgs e)
{
// Don't do anything if we've disabled shape mouse/touch input.
if (e.Key != Key.Escape)
return;
UnselectAll();
ShapeBeingDrawn = null; // COMPILER NO LIKEY
}
Run Code Online (Sandbox Code Playgroud)
那么集成可为空引用和依赖属性的正确方法是什么?我应该#pragma warning disable 围绕这些问题吗?如果可以的话,我想避免这种情况。
出现问题是因为属性在接口中ShapeBeingDrawn被声明为不可为空的引用类型,但在类中它被实现为可以为空的引用类型。因此编译器抱怨类中属性的返回类型与接口中的返回类型不匹配。IShapeILayerViewLayerViewIShape?
为了解决这个问题,我们应该确保接口和类都将属性声明为nullableor non-nullable。如果其中之一的声明不同,那么我们将再次收到编译器错误。
为什么会出现问题?
错误 CS8766:返回类型中引用类型 的可空性
'IShape? LayerView.ShapeBeingDrawn.get'与隐式实现的成员不匹配'IShape ILayerView.ShapeBeingDrawn.get'(可能是因为可空性属性)。
从错误信息中我们可以看到有一个ILayerView带有non-nullable属性的接口ShapeBeignDrawn:
interface ILayerView
{
IShape ShapeBeingDrawn { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
以及一个LayerView实现此接口但将属性声明ShapeBeignDrawn为nullable:
public class LayerView
{
public IShape? ShapeBeingDrawn
{
get => GetValue(ShapeBeingDrawnProperty) as IShape;
set => SetValue(ShapeBeingDrawnProperty, value);
}
}
Run Code Online (Sandbox Code Playgroud)
因此接口将属性声明为,non-nullable但类将其实现为nullable。因此编译器抱怨getter类中属性的返回类型与接口中的返回类型不匹配。
题:
首先,他们在谈论什么“隐式”实现的成员?
回答:
当我们声明一个属性时,编译器会为它隐式生成两个方法:get_PropertyName和set_PropertyName。因此编译器抱怨隐式实现getter方法的返回类型。
我们应该如何解决问题?
为了解决这个问题,我们应该确保接口和类都将属性声明为nullableor non-nullable。如果其中一个声明不同,那么我们将再次收到编译器错误CS8766。
这是一个重现问题的代码示例,并给出了如何修复它的提示。