gpt4 book ai didi

generics - 与 C# 8.0 可空引用类型结合时,是否可以为值或字符串类型声明泛型类型约束?

转载 作者:行者123 更新时间:2023-12-03 23:49:30 25 4
gpt4 key购买 nike

我写了两个抽象类来代表实体的基类:一个是 Id属性是 整数 , 另一个允许指定 Id 的类型使用泛型类型参数的属性 TId :

/// <summary>
/// Represents the base class for all entities.
/// </summary>
[System.Serializable]
public abstract class BaseEntity
{
/// <summary>
/// Gets or sets the ID of the entity.
/// </summary>
public int Id { get; set; }
}

/// <summary>
/// Represents the base class for all entities that have an ID of type <typeparamref name="TId"/>.
/// </summary>
/// <typeparam name="TId">
/// The type of the <see cref="Id"/> property.
/// </typeparam>
[System.Serializable]
public abstract class BaseEntity<TId>
{
/// <summary>
/// Gets or sets the ID of the entity.
/// </summary>
public TId Id { get; set; }
}

这些类是在我从事的几乎所有项目中使用的核心程序集中定义的。自从 C# 8.0 发布以来,我已经尝试启用 nullable reference types ,到目前为止效果很好。

但是,对于 BaseEntity<TId> ,编译器给出警告:

Non-nullable property 'Id' is uninitialized. Consider declaring the property as nullable.



我理解这个警告,但我似乎无法为我的用例解决这个问题。更具体地说,我想允许声明派生自的类型:
  • System.String ,即 BaseEntity<string>
  • 任何值类型,例如BaseEntity<System.Guid>或自定义结构

  • 由于 System.String不是值类型,这似乎是不可能的:如果我约束 TId对于结构( BaseEntity<TId> where TId : struct ),我不能声明 BaseEntity<string>不再。

    到目前为止,我发现的唯一解决方案(?)禁用警告,是初始化 Id属性及其默认值并使用 !运算符(operator):

    /// <summary>
    /// Represents the base class for all entities that have an ID of type <typeparamref name="TId"/>.
    /// </summary>
    /// <typeparam name="TId">
    /// The type of the <see cref="Id"/> property.
    /// </typeparam>
    [System.Serializable]
    public abstract class BaseEntity<TId>
    {
    /// <summary>
    /// Gets or sets the ID of the entity.
    /// </summary>
    public TId Id { get; set; } = default!;
    }

    但是,我想明确代码的意图: TId可以是值类型(例如,短、长、 System.Guid 、...)、 一个 System.String .

    这有可能吗?

    最佳答案

    不,没有这样的约束——无论您是否使用可为空的引用类型。

    您可能会做的是使用私有(private)构造函数来确保只有在基类型中声明的类型才能从 BaseEntity 派生。 ,然后使用两个特定版本:

    public abstract class BaseEntity<TId>
    {
    public TId Id { get; set; }

    private BaseEntity<TId>(Id id) => Id = id;

    public class StructEntity<T> : BaseEntity<T> where T : struct
    {
    public StructEntity() : base(default) {}
    }

    public class StringEntity : BaseEntity<string>
    {
    public StringEntity(string id) : base(id) {}
    }
    }

    那仍然可以让您使用 BaseEntity<T>在大多数地方,但任何时候你想构建一个实体,你都需要在这两者之间进行选择。

    我不知道这将如何与支持序列化联系起来,尽管我个人还是会避开二进制序列化。

    关于generics - 与 C# 8.0 可空引用类型结合时,是否可以为值或字符串类型声明泛型类型约束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59933006/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com