2

好的,几天来我一直在努力解决这个问题,在学习了 LINQ 之后,我认为我走在了正确的轨道上。但我有一个 SQL 大脑,有时很难将其转换为 C#。

我有两个数组,一个按字母顺序排序,另一个按 ID 排序。我需要按字母顺序排列第二个数组。ID 是连接因素。IEAID = P.ID。

这是我的数组和示例值;

private IGenericListItem[] _priceLevels = new IGenericListItem[0];
_priceLevels is in the form of {ID, Name}
{3, A}
{8, B}
{4, C}
{7, D}
{5, E}
{9, F}
{1, G}

编辑:更新此以显示 _assignmentControls 包含一个子数组。我没有做出如此疯狂的借口。它实际上包含 _priceLevels 的副本...

protected ArrayList _assignmentControls = new ArrayList();
_assignmentControls is in the form of {ID, LastPrice, NewPrice, _priceLevels[]}
{1, 1.00, 2.00, _priceLevels}
{2, 1.00, 2.00, _priceLevels}
{3, 1.00, 2.00, _priceLevels}
{4, 1.00, 2.00, _priceLevels}

部分问题是我试图比较/加入 ArrayList 和 IGenericListItem。

In SQL I would do something like this;
SELECT A.* 
FROM _assignmentControls A JOIN _priceLevels P
    ON A.ID = P.ID
ORDER BY P.Name

这将返回一个按 _priceLevels 中的值排序的 _assignmentControls 表。

在 C# LINQ 中,我做到了这一点,但似乎无法做到这一点;

        var sortedList =
            from a in _assignmentControls
            join p in _priceLevels on a equals p.ID
            orderby p.Name
            select _assignmentControls;

我在 join 和 orderby 下得到了红色的波浪线,并且 p.Name 中的 p 是红色的。A)它不起作用。B) 我不确定它是否会返回 sortedList 作为按 _priceLevels.Name 排序的 _assignmentControls 的排序版本。

编辑:当我将鼠标悬停在“加入”上时,我得到“方法'IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable,Func,Func ....'的类型参数不能从查询中推断出来。我是现在研究那个。

感谢您的关注!

4

3 回答 3

7

当我将鼠标悬停在“加入”上时,我得到“IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable, Func,Func....无法从查询中推断出该方法的类型参数。

我可以解释这里发生了什么,以便您可以追踪它。

当你说

from firstitem in firstcollection
join seconditem in secondcollection on firstkey equals secondkey
select result

编译器将其翻译为:

Enumerable.Join(
    firstcollection,
    secondcollection, 
    firstitem=>firstkey, 
    seconditem=>secondkey, 
    (firstitem, seconditem)=>result)

Enumerable.Join是一个泛型方法,有四个类型参数:第一个集合的元素类型、第二个集合的元素类型、键类型和结果类型。

如果您遇到该错误,那么根据您提供给编译器的信息,无法推断出这四件事之一。例如,也许:

  • 第一个集合的类型实际上不是一个序列。
  • 第二个集合的类型实际上不是一个序列。
  • 结果的类型无法推断
  • 这两个键的类型不一致,没有唯一的最佳类型。

最后一点是最有可能的。例如,假设第一个键是int,第二个键是short。由于 eachshort可以转换为int,int将获胜,并且第二个密钥将自动转换为int. 现在假设第一个键类型是Giraffe,第二个键类型是Tiger。两者都不比另一个更好。C# 不会说“哦,它们都是Animal,所以让我们选择它吧。” 相反,它表示您没有提供足够的信息来确定您的意思;您应该将其中一个投射到Animal然后它就变得清晰了。

说得通?

早在 2006 年,我就有一个半小时的视频来解释这个特性——这是我在编译器中添加有问题的特性的时候——所以如果你想要更深入的解释,请查看。

http://ericlippert.com/2006/11/17/a-face-made-for-email-part-three/

更新:我刚刚再次更仔细地阅读了您的问题:

部分问题是我试图比较/加入 anArrayList和 an IGenericListItem

有问题。序列的类型无法从ArrayList. 你不应该再使用ArrayList了。事实上,你不应该在 2005 年之后编写的任何代码中使用它。List<T>用于一些合适的 T。

于 2013-07-05T21:11:19.413 回答
4

你的select条款是错误的,应该是这样的:

    var sortedList =
        from a in _assignmentControls
        join p in _priceLevels on a equals p.ID
        orderby p.Name
        select a;

另一个问题是_assignmentControlstype ArrayList,它具有 type 的元素Object,因此编译器不知道 的实际类型a,并且不能将其用作连接条件,因为ap.ID.

您应该使用 a List<int>(假设p.ID是 type int)而不是ArrayList. 另一种选择是a明确指定类型:

    var sortedList =
        from int a in _assignmentControls
        join p in _priceLevels on a equals p.ID
        orderby p.Name
        select a;
于 2013-07-05T20:21:24.370 回答
3

我认为你应该写:

var sortedList =
                from a in _assignmentControls
                join p in _priceLevels on a.ID equals p.ID
                orderby p.AnotherValue
                select a;

当您从 _assignmentControls 中写入时 - 您正在声明一个变量,该变量引用要对其执行操作的序列中的当前元素。当您调用 select 时 - 您正在从序列中投影元素。想象它像传送带。

让我举一些转储数据的例子:

public class SomeCLass
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }

        public class AnotherClass
        {
            public int ID { get; set; }
            public int Value { get; set; }
            public int AnotherValue { get; set; }
        }

public void TestMEthod()
        {
            List<SomeCLass> _assignmentControls = new List<SomeCLass>()
                {
                    new SomeCLass() { ID = 1, Name = "test"},
                    new SomeCLass() { ID = 2, Name = "another test"}
                };
            List<AnotherClass> _priceLevels = new List<AnotherClass>()
                {
                    new AnotherClass() {ID = 1, AnotherValue = 15, Value = 13},
                    new AnotherClass() {ID = 2, AnotherValue = 5, Value = 13}
                };


            var sortedList =
            //here you're declaring variable a that will be like caret when you going through _assignmentControls
            from a in _assignmentControls
            join p in _priceLevels on a.ID equals p.ID
            orderby p.AnotherValue
            select a;


            foreach (var someCLass in sortedList)
            {
                Console.WriteLine(someCLass.Name);
            }
        }

结果:

another test
test
于 2013-07-05T20:16:41.220 回答