Отдельное объявление и создание словаря с анонимным ключом - PullRequest
0 голосов
/ 16 сентября 2009

В моем коде я создаю несколько таблиц подстановки.

var Dict1 = data1.ToDictionary(dim => new { dim.Val1,dim.Val2,.. }  );
var Dict2 = data2.ToDictionary(dim => new { dim.Val1,dim.Val2,.. }  );

иногда встречаются дублированные значения ключей, поэтому я попытался использовать блок catch

try
{
   var Dict1 = data1.ToDictionary(dim => new { dim.Val1,dim.Val2,.. }  );
}
catch (ArgumentException ex)
{
    Console.WriteLine("Duplicate values in Data1 {0}",ex);
    throw;
}

но такой подход означает, что Dicts не будет виден остальной части кода.

Есть идеи, как это сделать?

Редактировать: цель блока catch - сообщить, какой словарь не удалось создать.

Ответы [ 4 ]

2 голосов
/ 16 сентября 2009

Объявите и добавьте один элемент над попыткой, а затем добавьте остальные внутри. Поскольку вы особенно беспокоитесь о дублирующих ключах, добавление первого ключа / элемента дает вам тип без риска.

РЕДАКТИРОВАТЬ: Я думаю, что просто вывод типа, без добавления первого элемента, немного лучше. Хотя использование это немного громоздко, это облегчит добавление оставшихся элементов (в отличие от очистки словаря, а затем добавления - или необходимости добавлять все после 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);
0 голосов
/ 17 декабря 2009

Вы приложите много усилий, чтобы избежать объявления нового типа. Анонимные типы удобны, когда у вас есть очень специфическая конструкция данных, которую вы ожидаете никогда больше не использовать в каком-либо другом месте вашего кода. В этом случае вы хотите представлять один и тот же тип более чем в одном месте, поэтому лучшим решением, вероятно, является просто создание класса для представления этого типа. Вы можете сделать его закрытым вложенным классом, чтобы не загрязнять пространство типов вне этого класса.

0 голосов
/ 16 сентября 2009

Есть ли причина использовать блок try/catch? Вы не добавляете никакой ценности в свою программу, кроме записи в консоль. Если бы вы выполняли там фактическую обработку ошибок, я мог бы решить эту проблему, но я бы просто допустил исключение, а не пытался его перехватить.

0 голосов
/ 16 сентября 2009

Вы можете объявить переменную Dict1 вне блока try catch.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...