.net的通用方法VB.net与C#相比,因为当VB更灵活
本文关键字:VB net 因为 方法 相比 | 更新日期: 2023-09-27 18:20:20
有一个通用函数,它并不真正关心它在做什么(仅供参考,将一个对象列表对应到另一个对象),主要思想是它有两种类型Ts和Tp-
public static List<Tp> CreateAndFillList<Ts, Tp>(this IEnumerable<Ts> sItems) where Tp : class, new()
{
Type myType = default(Type);
PropertyInfo[] pSourceAllInfos = null;
if (pSourceAllInfos == null)
{
myType = typeof(Ts);
pSourceAllInfos = myType.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray();
}
PropertyInfo[] pTargetAllInfos = null;
if (pTargetAllInfos == null)
{
myType = typeof(Tp);
pTargetAllInfos = myType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(pi => pi.CanWrite).ToArray();
}
var joinedPI = (from spi in pSourceAllInfos
join tpi in pTargetAllInfos on spi.Name.ToLower() equals tpi.Name.ToLower()
select new { spi, tpi }).ToList();
List<Tp> retList = new List<Tp>();
foreach (var sItem in sItems)
{
Tp tpNewItem = new Tp();
foreach (var jpi in joinedPI)
{
jpi.tpi.SetValue(tpNewItem, jpi.spi.GetValue(sItem, null), null);
}
retList.Add(tpNewItem);
}
return retList;
}
有两个简单的类
public class SourceInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string SourceData { get; set; }
}
public class TargetInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string TargetData { get; set; }
}
我的问题是以下代码引发编译错误
private void button1_Click(object sender, EventArgs e)
{
List<SourceInfo> srcLst = new List<SourceInfo>();
srcLst.Add(new SourceInfo() { Id = 1, Name = "First", SourceData = "data1" });
srcLst.Add(new SourceInfo() { Id = 2, Name = "Second", SourceData = "data2" });
var q = from li in srcLst
select new { li.Id, li.Name };
dynamic qD = from li in srcLst
select new { li.Id, li.Name };
var resultLst = srcLst.CreateAndFillList<TargetInfo>();
//Using the generic method 'ExtensionTest.Extensions.CreateAndFillList<Ts,Tp>(System.Collections.Generic.IEnumerable<Ts>)' requires 2 type arguments
var resultLst1 = q.CreateAndFillList<TargetInfo>();
//Using the generic method 'ExtensionTest.Extensions.CreateAndFillList<Ts,Tp>(System.Collections.Generic.IEnumerable<Ts>)' requires 2 type arguments
var resultLst2 = qD.CreateAndFillList<TargetInfo>();
//works but will have to use dynamic...
}
同时在VB.Net中一切都很好!!!!
Dim lst As List(Of SourceInfo) = New List(Of SourceInfo)()
lst.Add(New SourceInfo() With {.Id = 1, .Name = "First"})
lst.Add(New SourceInfo() With {.Id = 2, .Name = "Second"})
Dim q = From li In lst
Select New With {li.Id, li.Name}
Dim retLst = lst.CreateAndFillList(Of TargetInfo)()
Dim retLst1 = q.CreateAndFillList(Of TargetInfo)()
我的问题是,我不想在任何地方都使用动态,因为它需要额外的编码,而且是运行时编译。
我在C#中做错了什么?请帮忙。
编译器消息非常清楚这个问题:您需要同时指定两个类型参数。如果你只指定一个,就不清楚它应该是两个参数中的哪一个
var resultLst = srcLst.CreateAndFillList<SourceInfo, TargetInfo>();
var resultLst1 = q.CreateAndFillList<SourceInfo, TargetInfo>();
这个:
dynamic qD = from li in srcLst
select new { li.Id, li.Name };
不需要是动态的。var
在这里更合适,它会给您带来编译时错误。如果你这样做,你会得到相同的错误qD
:
var resultLst2 = qD.CreateAndFillList<SourceInfo, TargetInfo>();
否则,您将只在运行时得到错误。
我在C#中做错了什么?
编译器不会部分推断泛型参数。使用dynamic
会将该检查推迟到运行时,在那里它很可能会失败。您需要在对CreateAndFillList
的调用中提供输入和输出通用参数。
var resultLst = srcLst.CreateAndFillList<SourceInfo, TargetInfo>();