是否可以使用布尔值评估编写连接?

时间:2013-08-14 13:24:28

标签: linq

我想写

CompareInfo myCompIntl = CompareInfo.GetCompareInfo( "es-ES" );
var SharedYomi = from ObjA in ClassListA
                 join ObjB in ClassListB
                 where CompareInfo.Compare(ObjA.Name, ObjB.Name) == 0
                 select new {stringA = stringA, string = string};

Linq强迫我用equals写连接。我无法通过布尔评估。 我怎么能这样做?

1 个答案:

答案 0 :(得分:0)

您不能使用LINQ lambda查询语法编写它。 join关键字要求您准确指定使用equals关键字进行比较的两个属性,因为这会映射到Join的第一个重载,它使用默认比较器来比较键。

但是,Join的重载会接受可能适合您的IEqualityComparer,您只需要使用方法查询语法。

由于您听起来不熟悉方法语法,因此以下是MSDN的一篇好文章:

http://msdn.microsoft.com/en-us/library/vstudio/bb397947.aspx

但是,基本上,你认为是“LINQ”的语法只是引用LINQ扩展的一种方式,而实际上只是围绕实现LINQ的IEnumerable扩展方法的语法糖。因此,例如,查询:

from x in y where x.IsActive orderby x.Name select x

它基本上与

相同
y.Where(x => x.IsActive).OrderBy(x => x.Name).Select(x => x);

在大多数情况下,每个查询子句都映射到特定IEnumerable方法的特定重载,但这些方法有许多其他重载,这些重载采用不同数量和类型的参数。

Join方法有点复杂,因为它们将两个序列作为输入,并允许您使用表达式组合它们的各个元素,但这个想法完全相同。典型的连接看起来像这样:

from x in y
join a in b on x.Id equals a.ParentId
select new { x.Id, x.Name, a.Date }

变为

y.Join(
  b, 
  x => x.Id, 
  a => a.ParentId, 
  (x, a) => new { x.Id, x.Name, a.Date });

这将使用其数据类型(int,string等)的默认比较来加入a.ParentIdx.Id。编译器直接将查询语法转换为方法语法,因此两者的行为完全相同。 (挑剔我自己的答案:从技术上讲,这些方法都在Enumerable类上,所以你实际上是在调用Enumerable.Join。但是当它们被实现为扩展方法时,你可以调用它们,编译器将弄清楚。)

在您的情况下,您需要传递一种不同的比较方法,因此您可以使用显式编码调用string.CompareJoin的另一个重载允许您提供IEqualityComparer<T>的实现来代替默认值。这将要求您在单独的类中实现IEqualityComparer<string>,因为没有简单的方法来创建匿名接口实现(可能是我从Java中遗漏的唯一功能)。对于你的例子,你想要这样的东西:

public class ComparerWithEncoding : IEqualityComparer<string>
{
  private CompareInfo compareInfo
  public ComparerWithEncoding ( string encoding )
  {
    this.compareInfo = CompareInfo.GetCompareInfo(encoding);
  }

  public bool Equals ( string a, string b )
  {
    return CompareInfo.Compare(a, b) == 0
  }

  public int GetHashCode(string a)
  {
    return a.GetHashCode();
  }
}

classListA.Join(
  ClassListB,
  ObjA => ObjA.Name,
  ObjB => ObjB.Name,
  (ObjA, ObjB) => new { stringA = ObjA.Foo, stringB = ObjB.Bar },
  new ComparerWithEncoding("es-ES"));