Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ Union不同类型-动态转换到接口?_C#_Linq_Casting_Union - Fatal编程技术网

C# LINQ Union不同类型-动态转换到接口?

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>'" 我已经做了研究,了解到不能跨不同类型执行联合,我还了解,如果匿名类型共享相同的属性,则可以对其执行联合

我有10个表,它们以不同的类型呈现给LINQ,但共享完全相同的属性。当我尝试在它们上运行联合时,编译器告诉我:

"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)这个答案太棒了。。。在读这篇文章之前,我根本没有真正阅读过协方差,因为我不知道这是一个如此强大的新语言特性。再次感谢您分享您的知识,杰普!