在 LINQ 内部联接中保留空值

Preserving nulls in LINQ inner joins

此代码在 specialthings 上执行内部联接,然后将索引生成到相应匹配项的 things 中:

object[] special = {      'b',    null, 5.0f,      "notme" };
object[] things  = { "a", 'b', 3, null, 5.0f, 6.0          };

var specialThingIndices = from tn in things.Select((t,n) => (t,n)) 
                          join s in special on tn.t equals s
                          select tn.n;

foreach (var n in specialThingIndices)
    Console.WriteLine($"[{n}] = {Convert.ToString(things[n])}, {things[n] is null}");

它输出:

[1] = b, False
[4] = 5, False

但是,null 出现在两个数组中,我不想跳过它。所以我想要它输出的是:

[1] = b, False
[3] = , True
[4] = 5, False

为什么它看不到 nulls,我怎样才能让它保留它们?

我尝试在各个地方手动应用 DefaultIfEmpty() 但没有成功。我也尝试用 == 替换 equals 但我猜这不是有效的语法。我想不出别的了。

可运行的示例是 here

如果为 null,您可以 select 默认值,例如 "<null>" 字符串。

...
object[] special = { 'b', null, 5.0f, "notme" };
object[] things = { "a", 'b', 3, null, 5.0f, 6.0 };

var specialThingIndices = from tn in things.Select(x => x ?? "<null>").Select((t, n) => (t, n))
                          join s in special.Select(x => x ?? "<null>") on tn.t equals s
                          select tn.n;

foreach (var n in specialThingIndices)
    Debug.WriteLine($"[{n}] = {Convert.ToString(things[n])}, {things[n] is null}");
...

编辑 使用 Where 而不是 join 的另一种解决方案。

...
object[] special = { 'b', null, 5.0f, "notme" };
object[] things = { "a", 'b', 3, null, 5.0f, 6.0 };

var specialThingIndices = from tn in things.Select((t, n) => (t, n))
                          where special.Any(s => Equals(s, tn.t))
                          select tn.n;

foreach (var n in specialThingIndices)
    Debug.WriteLine($"[{n}] = {Convert.ToString(things[n])}, {things[n] is null}");
...