You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SqliteAsyncConnection.Table<T>时required成员的约束冲突问题

解决带required成员的实体类与SQLite.NET泛型约束冲突的问题

问题重现

定义包含required字段的实体类以消除null警告:

public class CategoryTable
{
    public CategoryTable() { }  

    [Column("id")]
    public required int Id { get; set; }

    [Column("name")]
    public required string Name { get; set; }
}

编写泛型查询方法时,Table<CategoryTable>()触发CS0310错误:

CategoryTable必须是具有公共无参构造函数的非抽象类型,才能用作泛型类型或方法SQLiteAsyncConnection.Table<T>()的参数T

添加where CategoryTable : class, new()约束后,CS0310解决,但调用await DatabaseConn.GetCategoryAsync<CategoryTable>()时触发CS9040错误:

CategoryTable无法满足泛型类型或方法IDatabaseService.GetCategoryAsync<CategoryTable>()中参数CategoryTable的new()约束,因为CategoryTable包含required成员。

解决方案

1. 在无参构造函数中初始化required字段(C# 11+)

C# 11及以上允许在无参构造函数中为required字段赋值,这样既满足new()约束,又保证required字段不会为null:

public class CategoryTable
{
    public CategoryTable() 
    {
        Id = 0; // 可根据业务设置数据库默认值
        Name = string.Empty;
    }  

    [Column("id")]
    public required int Id { get; set; }

    [Column("name")]
    public required string Name { get; set; }
}

这种方式下,SQLite.NET可以通过无参构造创建实例,同时外部手动创建实例时,required字段的强制初始化要求依然生效。

2. 改用[NotNull]属性替代required(兼容旧版本C#)

如果项目使用C# 10及以下,或者不想修改构造函数,可以启用nullable上下文(#nullable enable),并使用[NotNull]属性标记字段,既避免null警告,又满足new()约束:

#nullable enable
public class CategoryTable
{
    public CategoryTable() { }  

    [Column("id")]
    [NotNull]
    public int Id { get; set; }

    [Column("name")]
    [NotNull]
    public string Name { get; set; } = string.Empty;
}

注意引用类型字段(如string)需要赋默认值(比如string.Empty),否则仍会有null警告;值类型(如int)本身不可为null,配合[NotNull]即可消除警告。

核心原因

SQLite.NET的Table<T>方法要求T拥有公共无参构造函数,而C#中包含required字段的类默认不满足new()约束——因为new()要求可以通过new T()创建有效实例,但required字段未初始化的实例是无效的。只有当无参构造函数显式初始化了所有required字段时,类才满足new()约束。

内容的提问来源于stack exchange,提问作者Shawn Crane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 04:35:55