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

C#泛型方法无法编译,如何实现通用字段重复校验?

如何实现校验字段重复的泛型方法?

现有集合与非泛型校验方法:

public IEnumerable<UserRole> SystemUserRoles { get; set; }
public IEnumerable<User> Users { get; set; }

private bool CheckUserRoleNameForDoubling(UserRole userRole)
{
    var userRoles = SystemUserRoles.ToList();
    userRoles.Remove(userRole);
    
    return !userRoles.Select(p => p.Name).Contains(userRole.Name);
}

private bool CheckLoginForDoubling(User user)
{
    var userList = Users.ToList();
    userList.Remove(user);
    
    return !userList.Select(p => p.Login).Contains(user.Login);
}

尝试编写泛型方法但编译失败:

private bool CheckFieldForDoubling<T>(T obj, IEnumerable<T> col, string field)
{
    var list = col.ToList();
    list.Remove(obj);

    return !list.Select(p => ((T)p)[field]).Contains(obj[field]);
}

报错信息:无法对类型为'T'的表达式应用索引器[]

UPDATE1:这些方法用于在集合对象添加/编辑后、存入数据库前做重复校验。


方案1:使用委托(推荐,类型安全且高效)

放弃字符串传字段名的方式,改用Func<T, object>委托传入字段选择逻辑,既保证类型安全,又避免反射带来的性能损耗:

private bool CheckFieldForDoubling<T>(T obj, IEnumerable<T> col, Func<T, object> fieldSelector)
{
    var list = col.ToList();
    list.Remove(obj);
    var targetValue = fieldSelector(obj);
    return !list.Select(fieldSelector).Contains(targetValue);
}

调用示例:

// 校验UserRole的Name字段
CheckFieldForDoubling(role, SystemUserRoles, r => r.Name);
// 校验User的Login字段
CheckFieldForDoubling(user, Users, u => u.Login);

方案2:使用反射(适配字符串字段名场景)

如果必须通过字符串指定字段名,可通过反射获取属性/字段的值来实现:

using System.Reflection;

private bool CheckFieldForDoubling<T>(T obj, IEnumerable<T> col, string fieldName)
{
    var list = col.ToList();
    list.Remove(obj);
    
    // 优先获取属性(如果是字段则替换为GetField)
    PropertyInfo prop = typeof(T).GetProperty(fieldName);
    if (prop == null)
        throw new ArgumentException($"类型{typeof(T)}中不存在名为{fieldName}的属性");
    
    var targetValue = prop.GetValue(obj);
    return !list.Any(item => Equals(prop.GetValue(item), targetValue));
}

调用示例:

// 用nameof避免硬编码字符串出错
CheckFieldForDoubling(role, SystemUserRoles, nameof(UserRole.Name));
CheckFieldForDoubling(user, Users, nameof(User.Login));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 19:36:20