Реализация левого внешнего соединения с помощью методов расширения может выглядеть как
public static IEnumerable<Result> LeftJoin<TOuter, TInner, TKey, Result>(
this IEnumerable<TOuter> outer, IEnumerable<TInner> inner
, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector
, Func<TOuter, TInner, Result> resultSelector, IEqualityComparer<TKey> comparer)
{
if (outer == null)
throw new ArgumentException("outer");
if (inner == null)
throw new ArgumentException("inner");
if (outerKeySelector == null)
throw new ArgumentException("outerKeySelector");
if (innerKeySelector == null)
throw new ArgumentException("innerKeySelector");
if (resultSelector == null)
throw new ArgumentException("resultSelector");
return LeftJoinImpl(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer ?? EqualityComparer<TKey>.Default);
}
static IEnumerable<Result> LeftJoinImpl<TOuter, TInner, TKey, Result>(
IEnumerable<TOuter> outer, IEnumerable<TInner> inner
, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector
, Func<TOuter, TInner, Result> resultSelector, IEqualityComparer<TKey> comparer)
{
var innerLookup = inner.ToLookup(innerKeySelector, comparer);
foreach (var outerElment in outer)
{
var outerKey = outerKeySelector(outerElment);
var innerElements = innerLookup[outerKey];
if (innerElements.Any())
foreach (var innerElement in innerElements)
yield return resultSelector(outerElment, innerElement);
else
yield return resultSelector(outerElment, default(TInner));
}
}
. Затем в результате выборщик должен заботиться о нулевых элементах. Fx.
static void Main(string[] args)
{
var inner = new[] { Tuple.Create(1, "1"), Tuple.Create(2, "2"), Tuple.Create(3, "3") };
var outer = new[] { Tuple.Create(1, "11"), Tuple.Create(2, "22") };
var res = outer.LeftJoin(inner, item => item.Item1, item => item.Item1, (it1, it2) =>
new { Key = it1.Item1, V1 = it1.Item2, V2 = it2 != null ? it2.Item2 : default(string) });
foreach (var item in res)
Console.WriteLine(string.Format("{0}, {1}, {2}", item.Key, item.V1, item.V2));
}
Насколько я знаю, даже если Dll был построен с конфигурацией Debug, он не будет содержать всех символов, необходимых для отладки. Вам все равно понадобится его файл символов, который создается при создании. Я предполагаю, что вы не создали DLL самостоятельно, потому что иначе Visual Studio должна будет самостоятельно найти файл символа на вашем диске. Файл символов имеет .pdb как расширение и обычно находится внутри папки сборки. Вам нужно найти его и сообщить Visual Studio, где его искать во время сеанса отладки. Когда вы нашли файл символа, выберите «Отладка» в строке меню Visual Studio и следуйте по этому пути: «Параметры» => «Отладка» => «Символы». Нажмите кнопку с зеленым знаком плюс, чтобы добавить место, где находится файл символа. Обратите внимание, что вам нужно только добавить местоположение файла, указав его имя не требуется.