【问题标题】:System.Linq.Dynamic.Core cannot compare 'object' typeSystem.Linq.Dynamic.Core 无法比较“对象”类型
【发布时间】:2020-11-12 03:23:28
【问题描述】:

我正在尝试使用以下模型运行动态查询:

public class Index
{
    public long Position { get; set; }

    public object[] Values { get; set; }
}

还有这样的数据样本:

var indexes = new Dictionary<long, Index>();
indexes.Add(1, new Index { Position = 1000, Values = new object[3] { "Welly", "Chandra", 26 } });
indexes.Add(2, new Index { Position = 1001, Values = new object[3] { "Darma", "Angelo", 25 } });
indexes.Add(3, new Index { Position = 1002, Values = new object[3] { "Abby", "Yeremia", 28 } });
indexes.Add(4, new Index { Position = 1003, Values = new object[3] { "Yonathan", "Gunawan", 22 } });
indexes.Add(5, new Index { Position = 1004, Values = new object[3] { "Aldy", "Santoso", 24 } });
var queryable = indexes.Values.AsQueryable();
var result = queryable.Where("Values[1] = \"Yeremia\" || Values[2] = 24").ToList();

但它总是抛出异常:

System.InvalidOperationException: The binary operator Equal is not defined for the types 'System.Object' and 'System.Int32'.

这里不能使用object数据类型吗?

【问题讨论】:

    标签: c# linq dynamic-linq


    【解决方案1】:

    如果您使用.Equals() 是可能的,它将首先检查类型是否相同,如果不同,将执行转换为运行时类型。

    var result = queryable.Where(
        "Values[1].Equals(\"Yeremia\") || Values[2].Equals(24)").ToList();
    

    如 cmets 中所述,比较对象时存在挑战。对于==,您无法将Int32 与没有强制转换的对象进行比较。同样,当使用.Equals() 时,不能让左边的值为 null,否则会抛出 NullReferenceException。

    如果可能的话,更好的方法是像 ValueTuple 这样的强类型,并通过名称而不是索引来引用。这不仅可以避免 NullReferenceExceptions,而且还可以避免装箱和强制转换操作。

    public class Index
    {
        public long Position { get; set; }
        public (string, string, int) Values { get; set; }
    }
    
    var indexes = new Dictionary<long, Index>();
        indexes.Add(1, new Index { Position = 1000, Values = ("Welly", "Chandra", 26) });
        indexes.Add(2, new Index { Position = 1001, Values = ("Darma", "Angelo", 25) });
        indexes.Add(3, new Index { Position = 1002, Values = ("Abby", "Yeremia", 28) });
        indexes.Add(4, new Index { Position = 1003, Values = ("Yonathan", "Gunawan", 22) });
        indexes.Add(5, new Index { Position = 1004, Values = ("Aldy", "Santoso", 24) });
        
    var queryable = indexes.Values.AsQueryable();
    var result = queryable.Where(
        "Values.Item2 == \"Yeremia\" || Values.Item3 == 24").ToList();
    

    【讨论】:

    • 谢谢,它有效。那么,所有比较都使用.Equals() 而不是= 运算符更好吗?
    • So, is it better for all comparisons to use .Equals() instead of = operator? 如果左侧可以是null,则不是。
    • @JustinusHermawan 对于这类事情总是如此,答案是“视情况而定”。 mjwills 强调了一个完美的例子,说明什么时候不建议这样做......例如,在您可能导致 NullReferenceException 的情况下。
    • 哦,我明白了,我想我可以保证object[] 值,它们将始终具有not null 值。
    • ValueTuple 可能是可能的,但是由于我的Values 的长度不确定并且具有动态类型,我想我需要使用Array 来代替。
    猜你喜欢
    • 2010-10-17
    • 1970-01-01
    • 2019-06-25
    • 2021-12-31
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    相关资源
    最近更新 更多