Объявите и добавьте один элемент над попыткой, а затем добавьте остальные внутри. Поскольку вы особенно беспокоитесь о дублирующих ключах, добавление первого ключа / элемента дает вам тип без риска.
РЕДАКТИРОВАТЬ: Я думаю, что просто вывод типа, без добавления первого элемента, немного лучше. Хотя использование это немного громоздко, это облегчит добавление оставшихся элементов (в отличие от очистки словаря, а затем добавления - или необходимости добавлять все после 1-го - действительно только выполнимо, если вы потребляете IEnumerable).
var dict1 = InferDictionary(new { Value1 = 0, Value2 = "string" }, new DataItem());
try {
data1.AddToDictionary(
dict1,
dim => new { Value1 = dim.Val1, Value2 = dim.Val2 }
);
} catch ... {
...
}
static IDictionary<TKey, TValue> InferDictionary<TKey, TValue>(TKey keyPrototype, TValue valuePrototype) {
return new Dictionary<TKey, TValue>();
}
Или создайте вспомогательную функцию, чтобы поймать исключение для вас:
var dict1 = TryCatch(
() =>
data1.ToDictionary(dim => new {
Value1 = dim.Val1,
Value2 = dum.Val2
}
, (ArgumentException ex) => {
Console.WriteLine("Duplicate values in Data1 {0}", ex);
// throw(ex) works as well, and shouldn't screw the callstack up much
// But I happen to like making it explicit
return false;
}
);
static TResult TryCatch<TResult, TException>(Func<TResult> @try, Func<TException, bool> @catch) where TException : Exception {
try {
return @try();
} catch (Exception ex) {
TException tEx = ex as TException;
if (tEx != null && @catch(ex)) {
// handled
} else {
throw;
}
}
}
Предостережение в том, что вы не можете назвать TryCatch<,>
"естественными" способами:
// Not enough info to infer TException
var d = TryCatch(() => DoStuff(), ex => true);
// Can't infer only TResult
var d = TryCatch<ArgumentException>(() => DoStuff(), ex => true);
, который, поскольку вы не можете указать TResult
, приводит к несколько странному синтаксису объявления TException
в лямбда-выражении:
var d = TryCatch(() => DoStuff(), (ArgumentException ex) => true);