我有10个表作为不同类型呈现给LINQ,但共享完全相同的属性。当我尝试在它们上运行联合时,编译器告诉我:
"Argument 2: cannot convert from 'System.Collections.IEnumerable' to 'System.Collections.Generic.IEnumerable<LINQPad.User.TelJun2011>'"
代码看起来像这样
var jul = (from n in TelJul2011s select n);
var jun = (from p in TelJun2011s select p);
jun.Union(jul).Dump();
我已经完成了我的研究并理解不能在不同类型之间执行联合,我也理解,如果联合共享相同的属性,则可以对匿名类型执行联合。这个选项对我来说不起作用,因为我需要所有表中的所有属性,并且不希望必须输出相同的匿名类型10次 - 每个变量一次。我希望编译器根据所有属性相同的事实推断它们都是相同的类型。
我已经尝试使用AsQueryable()类型函数和“as”关键字转换为IEnumberable,Iqueryable,Datatable等。这些似乎都不适合我。
我想知道是否通过动态转换为父类型来实现此目的。我无法编辑类的初始声明,因此无法在它们上实现一个通用接口来强制转换。但是有一些方法可以在使用它们时将这些类型转换为通用接口,而无需编写从每种类型到父接口的转换吗?
感谢您的任何建议!
答案 0 :(得分:8)
Union
的结果将是IEnumerable<Xxx>
,但在这种情况下,您必须指定Xxx
是什么。如果类型TelJun2011
和TelJul2011
不是结构(值类型),您可以使用此IEnumerable<out T>
的协方差 :
jun.Union<object>(jul)
这是有效的,因为TelJun2011
和TelJul2011
都是object
,然后协方差IEnumerable<TelJun2011>
和IEnumerable<TelJul2011>
都是IEnumerable<object>
。
当然object
不具备TelJun2011
和TelJul2011
共有的所有属性。如果这两种类型具有更有用的公共基类或实现一个通用接口会更好,因为那样你可以说例如:
jun.Union<ITelMonth>(jul)
其中ITelMonth
是包含所需公共属性的某种类型。
答案 1 :(得分:0)
“问题”是C#的静态类型系统不允许你想要实现的目标。在将它们合并之前,您必须将对象强制转换为基类型。这意味着如果两者只有System.Object
共同点,则必须将其转换为object
或(对于.net 4.0)dynamic
。
后者将强制进行动态类型检查:
class A
{
public int Integer { get; set; }
}
class B
{
public int Integer { get; set; }
}
class Program
{
public static void main(string[] args)
{
var a = new[] { new A { Integer = 5 }, new A { Integer = 6 }, new A { Integer = 7 } };
var b = new[] { new B { Integer = 1 }, new B { Integer = 2 }, new B { Integer = 3 } };
var u = a.Cast<dynamic>().Union(b).ToArray();
var i1 = u[0].Integer;
var i2 = u[1].Integer;
var i3 = u[2].Integer;
var i4 = u[3].Integer;
var i5 = u[4].Integer;
var i6 = u[5].Integer;
}
}
在我看来,这不是一个理想的解决方案,但这可能对你有帮助。
答案 2 :(得分:0)
如果您正在使用EntityFramework(或任何其他框架,我猜),自动生成的类标记为partial
,如下所示:
<强> /Project/Data/TelJun2011.cs 强>
namespace Project.Data
{
using System;
using System.Collections.Generic;
public partial class TelJun2011
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
<强> /Project/Data/TelJul2011.cs 强>
namespace Project.Data
{
using System;
using System.Collections.Generic;
public partial class TelJul2011
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
partial
的含义是您可以为同一个类创建另一个文件。生成的类没有实现接口,但您可以轻松地实现自定义接口,如下所示:
<强> /Project/Data/ITelMonth.cs 强>
namespace Project.Data
{
public interface ITelMonth
{
int Id { get; set; }
string Name { get; set; }
string Description { get; set; }
}
}
<强> /Project/Data/Partial/TelJun2011.cs 强>
namespace Project.Data
{
public partial class TelJun2011 : ITelMonth { }
}
<强> /Project/Data/Partial/TelJul2011.cs 强>
namespace Project.Data
{
public partial class TelJul2011 : ITelMonth { }
}
如果正确定义了接口,那么我们可以简单地执行此操作:
var jul = (from n in TelJul2011s select (ITelMonth)n);
var jun = (from p in TelJun2011s select (ITelMonth)p);
var bimester = jun.Union(jul);
你甚至可以访问像这样的公共属性:
foreach (var e in bimester)
{
e.Id.Dump();
}