C#泛型问题
我对泛型有点生疏,尝试执行以下操作,但编译器抱怨:C#泛型问题,c#,generics,collections,C#,Generics,Collections,我对泛型有点生疏,尝试执行以下操作,但编译器抱怨: protected List<T> PopulateCollection(DataTable dt) where T: BusinessBase { List<T> lst = new List<T>(); foreach (DataRow dr in dt.Rows) { T t = new T(dr); lst.Add(t); } r
protected List<T> PopulateCollection(DataTable dt) where T: BusinessBase
{
List<T> lst = new List<T>();
foreach (DataRow dr in dt.Rows)
{
T t = new T(dr);
lst.Add(t);
}
return lst;
}
受保护列表PopulateCollection(DataTable dt),其中T:BusinessBase
{
List lst=新列表();
foreach(数据行dr在dt.行中)
{
T=新的T(dr);
第1条增补(t);
}
返回lst;
}
如您所见,我试图将表的内容转储到对象中(通过向构造函数传递数据行),然后将对象添加到集合中。它抱怨T不是它知道的类型或名称空间,我不能在非泛型声明中使用where
这是不可能的吗?您可能需要在T上添加
新的
通用约束,如下所示:
protected List<T> PopulateCollection<T>(DataTable dt) where T : BusinessBase, new()
...
protectedlist PopulateCollection(DataTable dt),其中T:BusinessBase,new()
...
我无法将数据行传递给构造函数,但您可以通过将其分配给BusinessBase
where T: BusinessBase
应该有new()的限制,我想添加了两个大问题:
- 不能指定接受参数的构造函数约束
- 您的方法当前不是泛型的-它应该是
而不是PopulateCollection
PopulateCollection
T:BusinessBase
,因此为了解决第一个问题,我建议您在BusinessBase
中添加一个抽象(或虚拟)方法:
public abstract void PopulateFrom(DataRow dr);
还将无参数构造函数约束添加到T
然后,您的方法可以变成:
protected List<T> PopulateCollection(DataTable dt)
where T: BusinessBase, new()
{
List<T> lst = new List<T>();
foreach (DataRow dr in dt.Rows)
{
T t = new T();
t.PopulateFrom(dr);
lst.Add(t);
}
return lst;
}
或者,您可以将其本身作为扩展方法(同样假设为.NET 3.5),并传入一个函数以返回实例:
static List<T> ToList<T>(this DataTable dt, Func<DataRow dr, T> selector)
where T: BusinessBase
{
return dt.AsEnumerable().Select(selector).ToList();
}
这假设您返回到一个构造函数获取一个DataRow
。这样做的好处是允许您编写不可变类(以及没有无参数构造函数的类),但这确实意味着您不能在没有“factory”函数的情况下进行一般性工作。唯一可以指定允许创建新实例的类是new()
——基本上是无参数构造函数。要避免这种情况,请执行以下操作之一:
interface ISupportInitializeFromDataRow
{
void InitializeFromDataRow(DataRow dataRow);
}
protected List<T> PopulateCollection<T>(DataTable dt)
where T : BusinessBase, ISupportInitializeFromDataRow, new()
{
List<T> lst = new List<T>();
foreach (DataRow dr in dt.Rows)
{
T t = new T();
t.InitializeFromDataRow(dr);
lst.Add(t);
}
return lst;
}
接口ISupportInitializeFromDataRow
{
void InitializeFromDataRow(DataRow DataRow);
}
受保护列表PopulateCollection(数据表dt)
其中T:BusinessBase,ISupportInitializeFromDataRow,new()
{
List lst=新列表();
foreach(数据行dr在dt.行中)
{
T=新的T();
t、 初始化FromDataRow(dr);
第1条增补(t);
}
返回lst;
}
或
受保护的列表PopulateCollection(数据表dt,Func builder)
where T:BusinessBase
{
List lst=新列表();
foreach(数据行dr在dt.行中)
{
T=建造商(dr);
第1条增补(t);
}
返回lst;
}
一种可能的方法是:
protected List<T> PopulateCollection<T>(DataTable dt) where T: BusinessBase, new()
{
List<T> lst = new List<T>();
foreach (DataRow dr in dt.Rows)
{
T t = new T();
t.DataRow = dr;
lst.Add(t);
}
return lst;
}
protectedlist PopulateCollection(DataTable dt),其中T:BusinessBase,new()
{
List lst=新列表();
foreach(数据行dr在dt.行中)
{
T=新的T();
t、 DataRow=dr;
第1条增补(t);
}
返回lst;
}
这是可能的。我的框架中有完全相同的东西。我和你的问题完全一样,我就是这样解决的。发布框架中的相关片段。如果我记得正确的话,最大的问题是需要调用无参数构造函数
public class Book<APClass> : Book where APClass : APBase
private DataTable Table ; // data
public override IEnumerator GetEnumerator()
{
for (position = 0; position < Table.Rows.Count; position++)
yield return APBase.NewFromRow<APClass>(Table.Rows[position], this.IsOffline);
}
...
public class APBase ...
{
...
internal static T NewFromRow<T>(DataRow dr, bool offline) where T : APBase
{
Type t = typeof(T);
ConstructorInfo ci;
if (!ciDict.ContainsKey(t))
{
ci = t.GetConstructor(new Type[1] { typeof(DataRow) });
ciDict.Add(t, ci);
}
else ci = ciDict[t];
T result = (T)ci.Invoke(new Object[] { dr });
if (offline)
result.drCache = dr;
return result;
}
public class Book:Book其中APClass:APBase
私有数据表;//数据
公共重写IEnumerator GetEnumerator()
{
对于(位置=0;位置
在此场景中,基类有一个静态方法,使用接受tablerow的构造函数实例化其派生类的对象。public class BusinessBase{public DataRow DataRow{get;set;}+我清楚这些问题,对于最后一个版本,我不认为中间版本比foreach更简单。在这种情况下,我没有编辑的权力,所以任何人都可以更改return dt.Rows.AsEnumerable().Select(selector.ToList();return dt.AsEnumerable().Select(selector.ToList());因为AsEnumerable是DataTable上的扩展方法,而不是.Rows集合上的扩展方法。
protected List<T> PopulateCollection<T>(DataTable dt, Func<DataRow, T> builder)
where T : BusinessBase
{
List<T> lst = new List<T>();
foreach (DataRow dr in dt.Rows)
{
T t = builder(dr);
lst.Add(t);
}
return lst;
}
protected List<T> PopulateCollection<T>(DataTable dt) where T: BusinessBase, new()
{
List<T> lst = new List<T>();
foreach (DataRow dr in dt.Rows)
{
T t = new T();
t.DataRow = dr;
lst.Add(t);
}
return lst;
}
public class Book<APClass> : Book where APClass : APBase
private DataTable Table ; // data
public override IEnumerator GetEnumerator()
{
for (position = 0; position < Table.Rows.Count; position++)
yield return APBase.NewFromRow<APClass>(Table.Rows[position], this.IsOffline);
}
...
public class APBase ...
{
...
internal static T NewFromRow<T>(DataRow dr, bool offline) where T : APBase
{
Type t = typeof(T);
ConstructorInfo ci;
if (!ciDict.ContainsKey(t))
{
ci = t.GetConstructor(new Type[1] { typeof(DataRow) });
ciDict.Add(t, ci);
}
else ci = ciDict[t];
T result = (T)ci.Invoke(new Object[] { dr });
if (offline)
result.drCache = dr;
return result;
}