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

VS2022下C#调用Oracle存储过程泛型列表转换编译错误求助

解决“无法将非泛型列表转换为泛型列表”编译错误

错误原因

你的编译错误核心是泛型列表的不变性:List<Employee>和List<Vendor>是具体类型的泛型列表,无法直接赋值给未约束的List<T>。即便Employee/Vendor继承自Common,List<Employee>也不与List<T>兼容(除非T被明确约束为对应派生类型)。

修复方案

通过以下步骤修改代码即可解决:

  1. 为GetFacility方法的泛型参数T添加约束,限定其为Common的子类且包含无参构造函数(匹配MapToList的泛型约束);
  2. 在switch分支中,将MapToList返回的具体列表转换为List<T>;
  3. 修复代码中的语法疏漏(如return语句缺失分号)。

修改后的完整代码

public class Common
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string State { get; set; }
}

public class Employee : Common
{
    public string SSN { get; set; }
}

public class Vendor : Common
{
    public string TaxNumber { get; set; }
}

// 新增泛型约束:T必须是Common的子类,且有无参构造
public async Task<List<T>> GetFacility<T>(string Facility_Type) where T : Common, new()
{
    using (EMPDB dbConnect = new EMPDB())
    {
        DbCommand dbCommand = dbConnect.Database.GetDbConnection().CreateCommand();
        dbCommand.CommandType = CommandType.StoredProcedure;
        dbCommand.CommandText = "GetFacilityReport";
        dbCommand.BuildSqlParameter("Facility_Type", OracleDbType.Varchar2, Facility_Type, ParameterDirection.Input);
        List<T> lstFacility_Response = null; // 初始化为null,避免空赋值问题

        if (dbCommand.Connection.State != ConnectionState.Open)
        {
            dbCommand.Connection.Open();
        }

        using (var reader = await dbCommand.ExecuteReaderAsync())
        {
            switch (Facility_Type)
            {
                case "Employee":
                    // 将List<Employee>转换为List<T>
                    lstFacility_Response = reader.MapToList<Employee>().Cast<T>().ToList();
                    break;

                case "Vendor":
                    // 将List<Vendor>转换为List<T>
                    lstFacility_Response = reader.MapToList<Vendor>().Cast<T>().ToList();
                    break;
            }
        }

        return lstFacility_Response ?? new List<T>(); // 处理空情况,返回空列表而非null
    }
}

public static List<T> MapToList<T>(this DbDataReader dr) where T : new()
{
    List<T> RetVal = null;
    var Entity = typeof(T);
    var PropDict = new Dictionary<string, PropertyInfo>();
    try
    {
        if (dr != null && dr.HasRows)
        {
            RetVal = new List<T>();
            var Props = Entity.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            PropDict = Props.ToDictionary(p => p.Name.ToUpper(), p => p);
            while (dr.Read())
            {
                T newObject = new T();
                for (int Index = 0; Index < dr.FieldCount; Index++)
                {
                    if (PropDict.ContainsKey(dr.GetName(Index).ToUpper()))
                    {
                        var Info = PropDict[dr.GetName(Index).ToUpper()];
                        if ((Info != null) && Info.CanWrite)
                        {
                            var Val = dr.GetValue(Index);
                            Info.SetValue(newObject, (Val == DBNull.Value) ? null : Val, null);
                        }
                    }
                }
                RetVal.Add(newObject);
            }
        }
    }
    catch (Exception)
    {
        throw;
    }
    return RetVal;
}

关键修改说明

  • 泛型约束:where T : Common, new() 告诉编译器T是Common的派生类,确保Employee/Vendor的实例可以安全转换为T;
  • 类型转换:Cast<T>().ToList() 将具体类型的列表转换为List<T>,解决泛型类型不兼容问题;
  • 空值处理:将初始列表设为null,返回时用?? new List<T>()确保不会返回null,提升代码健壮性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:55:20