将DTO类与ORM一起使用时,C#8中的可空引用类型


9

我在具有数据传输对象(DTO)类的项目中激活了此功能,如下所示:

public class Connection
    {
        public string ServiceUrl { get; set; }
        public string? UserName { get; set; }
        public string? Password { get; set; }
        //... others 
    }

但是我得到了错误:

CS8618:不可空的属性'ServiceUrl'未初始化。考虑将属性声明为可为空。

这是DTO类,因此我没有初始化属性。这是初始化类以确保属性为非null的代码的职责。

例如,呼叫者可以执行以下操作:

var connection = new Connection
{
  ServiceUrl=some_value,
  //...
}

我的问题:启用C#8的可空性上下文后,如何处理DTO类中的此类错误?


3
当按照显示方式进行构造初始化时,默认构造函数将运行(将ServiceUrl初始化为其默认值(对于字符串,该值为null))。然后,初始化语句运行。如果您希望它不可为空,则需要退出所有已初始化的构造函数
Flydog57 '19

POCO并不意味着它没有构造函数或未初始化属性。这意味着Plain Old C# Object。就像任何其他对象一样,而无需继承任何特殊类。我怀疑您有其他问题。-如何创建的DTOData Transfer Objects
帕纳约蒂斯Kanavos

This should be the responsibility of the one initializing the class to ensure that the properties are non-null该类应始终处于有效状态。如果null不允许,则该属性永远不能为null。也许,对于基本URL,应该使用专用类而不是基本字符串,该类可以具有值或“ None缺少” 值,例如F#中的Option类。C#8允许您编写此类并通过模式匹配检查它们
Panagiotis Kanavos 19/12/2

@Panagiotis Kanavos,在我的案例中,该类具有一个无参数构造函数的约束。所以我必须使用属性初始化程序:public string ServiceUrl { get; set; } = default! ;。我希望Roslyn将来可能有一种方法来处理超出ctor范围的后期初始化。我使用的是MayBe <T>(如Option类),但是我在c#8中将新代码切换为可空引用类型。
哈桑(M.Hassan),

NRT不是Maybes,实际上,Maybes现在变得更加重要且易于使用。当然,只要它们使用C#惯用法构建即可,使它们易于进行模式匹配
Panagiotis Kanavos

Answers:


9

EF Core和EF6建议使用下一个解决方案,请参见

1)通过null!与原谅操作员进行初始化

public string ServiceUrl { get; set; } = null! ;
//or
public string ServiceUrl { get; set; } = default! ;

2)使用后备字段:

        private string _ServiceUrl;
        public string ServiceUrl
        {
            set => _ServiceUrl = value;
            get => _ServiceUrl
                   ?? throw new InvalidOperationException("Uninitialized property: " + nameof(ServiceUrl));
        }



问题提到他不能使用!运算符。
Athanasios Kataras

我不能用!类型,但我提到的链接显示了如何使用null!进行初始化。这是一种解决方法。我修改了问题。
哈桑(M.Hassan)

8

如果它不可为空,那么在初始化对象时,编译器可以做什么?

字符串的默认值为null,因此您将

  1. 要么需要在声明中分配一个字符串默认值

    public string ServiceUrl { get; set; } = String.Empty;

  2. 或者在默认构造函数中初始化该值,以便摆脱警告

  3. 使用!运算符(您不能使用)

  4. 如robbpriestley所述,使其可为空。


4
当然,或者添加一个接受服务URL作为非空字符串的构造函数。
乔恩·斯基特

ServiceUrl'不能是= String.Empty。复杂类型的其他属性不能为null,因此我使用了以下方法default:'public MyClass MyProperty {get; 组; } =默认!以停止警告。该类(和其他类)是无参数的构造函数,最近在ctor范围之外初始化。
哈桑(M.Hassan),

0

在某些情况下可能会派上用场的另一件事:

[SuppressMessage("Compiler", "CS8618")]

可以在成员或整个类型的顶部使用。


要考虑的另一件事是#nullable disable在文件顶部添加以禁用整个文件的可空引用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.