C# LINQ Union不同类型-动态转换到接口?
我有10个表,它们以不同的类型呈现给LINQ,但共享完全相同的属性。当我尝试在它们上运行联合时,编译器告诉我:C# LINQ Union不同类型-动态转换到接口?,c#,linq,casting,union,C#,Linq,Casting,Union,我有10个表,它们以不同的类型呈现给LINQ,但共享完全相同的属性。当我尝试在它们上运行联合时,编译器告诉我: "Argument 2: cannot convert from 'System.Collections.IEnumerable' to 'System.Collections.Generic.IEnumerable<LINQPad.User.TelJun2011>'" 我已经做了研究,了解到不能跨不同类型执行联合,我还了解,如果匿名类型共享相同的属性,则可以对其执行联合
"Argument 2: cannot convert from 'System.Collections.IEnumerable' to 'System.Collections.Generic.IEnumerable<LINQPad.User.TelJun2011>'"
我已经做了研究,了解到不能跨不同类型执行联合,我还了解,如果匿名类型共享相同的属性,则可以对其执行联合。这个选项对我不起作用,因为我需要所有表中的所有属性,并且不希望必须键入相同的匿名类型10次——每个变量一次。我希望编译器根据所有属性都相同的事实推断它们都是相同的类型
我已经尝试使用AsQueryable()类型函数和“as”关键字强制转换为IEnumberable、Iqueryable、Datatable等。所有这些似乎都不适合我
我想知道是否有办法通过动态强制转换到父类型来实现这一点。我无法编辑类的初始声明,因此无法在类上实现要转换到的公共接口。但是,在使用这些类型时,是否有某种方法可以将它们向下转换为公共接口,而不必编写从每个类型到父接口的转换
谢谢你的建议 问题是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;
}
}
A类
{
公共整数{get;set;}
}
B类
{
公共整数{get;set;}
}
班级计划
{
公共静态void main(字符串[]args)
{
var a=new[]{newa{Integer=5},newa{Integer=6},newa{Integer=7};
var b=new[]{new b{Integer=1},new b{Integer=2},new b{Integer=3};
变量u=a.Cast().Union(b.ToArray();
变量i1=u[0]。整数;
var i2=u[1]。整数;
var i3=u[2]。整数;
var i4=u[3]。整数;
var i5=u[4]。整数;
var i6=u[5]。整数;
}
}
在我看来,这不是一个理想的解决方案,但这可能会对您有所帮助。联合的结果将是一个
IEnumerable
,但在这种情况下,您必须指定什么是Xxx
。如果类型TelJun2011
和TelJul2011
不是结构(值类型),您可以使用IEnumerable
的协方差,如下所示:
jun.Union<object>(jul)
其中,
ITelMonth
是包含您想要的公共属性的某种类型。如果您使用的是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; }
}
}
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; }
}
}
namespace Project.Data
{
public interface ITelMonth
{
int Id { get; set; }
string Name { get; set; }
string Description { get; set; }
}
}
namespace Project.Data
{
public partial class TelJun2011 : ITelMonth { }
}
namespace Project.Data
{
public partial class TelJul2011 : ITelMonth { }
}
/Project/Data/TelJul2011.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; }
}
}
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; }
}
}
namespace Project.Data
{
public interface ITelMonth
{
int Id { get; set; }
string Name { get; set; }
string Description { get; set; }
}
}
namespace Project.Data
{
public partial class TelJun2011 : ITelMonth { }
}
namespace Project.Data
{
public partial class TelJul2011 : ITelMonth { }
}
partial
的意思是可以为同一类创建另一个文件。生成的类不实现接口,但您可以很容易地创建并实现自定义接口,如下所示:
jun.Union<object>(jul)
/Project/Data/ITelMonth.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; }
}
}
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; }
}
}
namespace Project.Data
{
public interface ITelMonth
{
int Id { get; set; }
string Name { get; set; }
string Description { get; set; }
}
}
namespace Project.Data
{
public partial class TelJun2011 : ITelMonth { }
}
namespace Project.Data
{
public partial class TelJul2011 : ITelMonth { }
}
/Project/Data/Partial/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; }
}
}
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; }
}
}
namespace Project.Data
{
public interface ITelMonth
{
int Id { get; set; }
string Name { get; set; }
string Description { get; set; }
}
}
namespace Project.Data
{
public partial class TelJun2011 : ITelMonth { }
}
namespace Project.Data
{
public partial class TelJul2011 : ITelMonth { }
}
/Project/Data/Partial/TelJul2011.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; }
}
}
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; }
}
}
namespace Project.Data
{
public interface ITelMonth
{
int Id { get; set; }
string Name { get; set; }
string Description { get; set; }
}
}
namespace Project.Data
{
public partial class TelJun2011 : ITelMonth { }
}
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();
}
看来你已经是唯一的选择了。。。说你不能用它们。。。基本上,对于这些禁忌,答案是否定的。是的,就是这样。正确的解决方案是使用特定的非平板电脑类型(非匿名)并选择此类型。源代码的原因显然是坏的数据库设计,而不是坏的数据库设计。我正在评估使用linq作为查询多个来源的特别分析解决方案的可能性。多种源的联合是一种基本的SQL功能,通常用于分析,即使我同意这在生产或实际应用程序中是不好的做法。如果您使用EntityFramework,则将类创建为
分部
,然后您可以使用相同的分部创建另一个.cs文件,强制类实现具有所需属性的自定义接口。我认为您不需要Cast
方法。难道IEnumerable
的协方差不应该允许你只写:var u=a.Union(b)代码>这个答案太棒了。。。在读这篇文章之前,我根本没有真正阅读过协方差,因为我不知道这是一个如此强大的新语言特性。再次感谢您分享您的知识,杰普!