首页 > 解决方案 > 为 DTO 使用可空引用类型的最佳实践

问题描述

我有一个 DTO,它是通过从 DynamoDB 表中读取来填充的。说它目前看起来像这样:

public class Item
{
    public string Id { get; set; } // PK so technically cannot be null
    public string Name { get; set; } // validation to prevent nulls but this doesn't stop database hacks
    public string Description { get; set; } // can be null
}

是否有任何最佳实践来解决这个问题?我宁愿避免使用非无参数构造函数,因为它与 Dynamo SDK(以及其他)中的 ORM 很不符。

写起来对我来说似乎很奇怪,public string Id { get; set; } = "";因为这永远不会发生,因为这Id是一个 PK 并且永远不能为空。""即使它以某种方式发生了又有什么用呢?

那么这方面有什么最佳实践吗?

请注意:这是关于 C#8可空引用类型如果您不知道它们是什么最好不要回答。

标签: c#c#-8.0non-nullablenullable-reference-types

解决方案


作为一种选择,您可以将default文字与null forgiving operator

public class Item
{
    public string Id { get; set; } = default!;
    public string Name { get; set; } = default!;
    public string Description { get; set; } = default!;
}

由于您的 DTO 是从 DynamoDB 填充的,因此您可以使用MaybeNull/NotNull 后置条件属性来控制可空性

  • MaybeNull不可为空的返回值可能为空。
  • NotNull可为空的返回值永远不会为空。

但是这些属性只影响使用它们注释的成员的调用者的可空分析。通常,您将这些属性应用于方法返回、属性和索引器 getter。

因此,您可以考虑所有属性不可为空的并用MaybeNull属性装饰它们,表明它们返回可能的null

public class Item
{
    public string Id { get; set; } = "";
    [MaybeNull] public string Name { get; set; } = default!;
    [MaybeNull] public string Description { get; set; } = default!;
}

以下示例显示了更新Item类的用法。如您所见,第二行没有显示警告,但第三行显示

var item = new Item();
string id = item.Id;
string name = item.Name; //warning CS8600: Converting null literal or possible null value to non-nullable type.

或者您可以将所有属性设为可为空的,并用于NoNull指示返回值不能为nullId例如)

public class Item
{
    [NotNull] public string? Id { get; set; }
    public string? Name { get; set; }
    public string? Description { get; set; }
}

警告将与前面的示例相同。

输入参数、属性和索引器设置器也有AllowNull/DisallowNull 前置条件属性,以类似的方式工作。

  • AllowNull不可为空的输入参数可能为空。
  • DisallowNull可为空的输入参数永远不应为空。

我认为它不会对您有所帮助,因为您的类是从数据库中填充的,但是您可以使用它们来控制属性设置器的可空性,例如第一个选项

[MaybeNull, AllowNull] public string Description { get; set; }

而对于第二个

[NotNull, DisallowNull] public string? Id { get; set; }

可以在此开发博客文章中找到一些有用的详细信息和后置/前置条件示例


推荐阅读