VS2022下C#调用Oracle存储过程泛型列表转换编译错误求助
解决“无法将非泛型列表转换为泛型列表”编译错误
错误原因
你的编译错误核心是泛型列表的不变性:List<Employee>和List<Vendor>是具体类型的泛型列表,无法直接赋值给未约束的List<T>。即便Employee/Vendor继承自Common,List<Employee>也不与List<T>兼容(除非T被明确约束为对应派生类型)。
修复方案
通过以下步骤修改代码即可解决:
- 为
GetFacility方法的泛型参数T添加约束,限定其为Common的子类且包含无参构造函数(匹配MapToList的泛型约束); - 在switch分支中,将
MapToList返回的具体列表转换为List<T>; - 修复代码中的语法疏漏(如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
相关产品推荐
相关产品推荐

