Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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无效操作异常_C#_Linq - Fatal编程技术网

C#Linq无效操作异常

C#Linq无效操作异常,c#,linq,C#,Linq,我目前正在学习C#,并试图掌握LINQ的窍门。我正在尝试创建两个类:Store和products,我希望根据相应的ID返回其中的对象。我计划使用LINQ执行此操作,但遇到了此错误 System.InvalidOperationException:'未能比较数组中的两个元素。' ArgumentException:至少一个对象必须实现IComparable 当然,我试图通过添加如下内容将IComparable实现到类中: 公共类存储:i可比较 { 公共整数比较([AllowFull]存储其他)

我目前正在学习C#,并试图掌握LINQ的窍门。我正在尝试创建两个类:Store和products,我希望根据相应的ID返回其中的对象。我计划使用LINQ执行此操作,但遇到了此错误

System.InvalidOperationException:'未能比较数组中的两个元素。' ArgumentException:至少一个对象必须实现IComparable

当然,我试图通过添加如下内容将IComparable实现到类中:

公共类存储:i可比较
{
公共整数比较([AllowFull]存储其他)
{
抛出新的NotImplementedException();
}
}

所以您有两个表:
存储
产品
。显然,每个产品都属于一个商店,即外键
Product.StoreId
所指的商店

要进行调试,您已经尝试通过删除OrderBy语句来简化LINQ,以查看问题是在联接中还是在OrderBy中,当然,您还尝试只执行OrderBy而不执行联接。如果不是:去顽皮的地方半小时

下面的方法有效吗

仅加入:

var result = Stores.Join(Products,   // Join Stores and Products
    store => store.Id,               // from every Store take the primary key
    product => product.StoreId,      // from every Product take the foreign key

    // parameter resultSelector: from every matching Store and Product make one new:
    (store, product) => new
    {
        Market = store.Name,
        Product = product,
    })
    .ToList();
我想是的,因为例外是关于
IComparer
,而不是关于
IEqualityComparer

第二次尝试:订购商店和产品:

var sortedStores = marketPlaces.OrderBy(store => store.ID).ToList();
var sortedProducts = products.OrderBy(product => product.Names).ToList();
哪一个不行?我认为第二个是因为
Product.Names
是一个
字符串[]
。 您还没有告诉LINQ它应该如何比较两个
string[]
对象,或者换句话说:

我有两个
string[]
对象,哪一个应该先出现

因此,为了对产品名称进行排序,我们需要一个实现
IComparable
的对象。 制作一个IComparable并不难。问题可能更多地存在于需求中:如果您有两个字符串数组产品名称,哪一个成为第一个

public class ProductNamesComparer : IComparer<string[]>
{
    public int Compare(string[] x, string[] y)
    {
        // TODO: find out if x comes before y (return -1)
        // or after y                         (return +1)
        // or don't care                      (return 0)
    }
}
你想要的是:

Store 1 a "Supermarket" sells the following Products:
    "Vegetables" with price 3.00
    "Dairy" with price 2.00
    "Fruits" with price 1.50
Store 2 "Electronics" sells the following Products:
    "Portable Electronics" with price 200.00,
    "Stationary Electronics" with price 750.00,
    "Medical Electronics" with price 550.00
Store 3 ... etc.
如果需要,请首先将产品名称与其价格相结合:

StoreId = 1 has the following products with their prices:
            Name = "Vegetables"; Price 3.00
            Name = "Dairy"; Price 2.00
            Name = "Fruits"; Price 1.50
StoreId = 2 has the following products with their prices:
            Name = "Portable Electronics"; Price 200.00
            ...
我假设你的产品价格,第一个价格属于第一个产品名称,第二个价格是第二个产品名称的价格。我们必须以某种方式将它们匹配为组合:{Product Name;Product Price}

如果你有两个序列A和B,并且你想组合它们,这样你就有了<代码> {a(0),b(0)},{a(1),b { 1 }},{a[4],b[2 ] }< /> >等,考虑使用

的重载之一。 换句话说:从产品序列中的每个产品中,创建一个具有以下属性的新对象:

  • StoreId:产品的属性StoreId的值
  • NamePriceCompositions:包含<代码>{名称[0]、价格[0]}、{名称[1]、价格[1]}等组合的列表
注意:这只适用于每个产品名称只有一个价格的情况

因此,我们将您的原始产品序列转换为:

StoreId = 1, NamePriceCombinations = { { Name = "Vegetables"; Price 3.00},
                                       { Name = "Dairy"; Price 2.00},
                                       { Name = "Fruits"; Price 1.50} },
StoreId = 2; NamePriceCombinations = { { Name = "Portable Electronics"; Price 200.00},
                                       ...
我们只需要把它和商店联系起来。使用

如果您想要包含零个或多个子项的项目,如学校及其学生、客户及其订单或商店销售的产品,请使用GroupJoin

如果您想要相反的方式:“物品与它所属的(恰好一个)物品”,如学生与他就读的学校,或与销售此产品的商店的产品,请使用Join

我们想要“有他们销售的产品的商店”,所以我们使用GroupJoin

var storesWithTheProductsTheySell = MarketPlaces.GroupJoin(productsWithTheirPrices,

    store => store.Id,             // from every store take the primary key
    products => product.StoreId,   // from every product, take the foreign key

    (store, productsOfThisStore) => new
    {
         // Select the Store properties that you plan to use:
         Market = store.Name,
         ...

         Products = productsOfThisStore.Select(product => new
         {
             Name = product.Name,
             Price = product.Price,
         })
         .ToList(),
    });

当然,你可以在一个大LINQ声明中做到这一点。由于中间结果是IEnumerable,这不会大大提高效率,但我认为可读性会大大降低。

orderby market2.Names
-您是否尝试按
字符串[]
排序?您在代码中使用以下行抛出错误:throw new NotImplementedException();如果您注释掉“orderbymarket2.Names”一行,代码就会运行。@KlausGütter我试图按商店的ID来订购它。So:MarketPlace.Add(newstore{Name=“SuperMarket”,ID=1});添加(新产品{name=newstring[]{“蔬菜”、“乳制品”、“水果”},价格=新双[]{3.00,2.00,1.50},StoreID=1});相互通信。@jdweng我也试图更改它返回的内容,但错误仍然存在。另外,在评论这一行时,它会打印商店的名称,但不会打印其他列表中我想要的产品或其他值。非常感谢,这非常有用。事实上,我以前从未与IComparer合作过,所以这让人感到困惑,而且我对C#还是个新手,所以使用Enumerable有时对我来说很难理解。我对LINQ有一个基本的了解,我正在试图弄清楚Join是如何工作的,您对您的解决方案给出了非常好的解释。我不是很了解所有的事情,但我会研究它来了解更多并理解您的解决方案。
StoreId = 1, NamePriceCombinations = { { Name = "Vegetables"; Price 3.00},
                                       { Name = "Dairy"; Price 2.00},
                                       { Name = "Fruits"; Price 1.50} },
StoreId = 2; NamePriceCombinations = { { Name = "Portable Electronics"; Price 200.00},
                                       ...
var storesWithTheProductsTheySell = MarketPlaces.GroupJoin(productsWithTheirPrices,

    store => store.Id,             // from every store take the primary key
    products => product.StoreId,   // from every product, take the foreign key

    (store, productsOfThisStore) => new
    {
         // Select the Store properties that you plan to use:
         Market = store.Name,
         ...

         Products = productsOfThisStore.Select(product => new
         {
             Name = product.Name,
             Price = product.Price,
         })
         .ToList(),
    });