2009-08-27 2 views
18

Возможно ли изгнать аргументы параметра в C#? У меня есть:Кастинг C# вне параметров?

Dictionary<string,object> dict; // but I know all values are strings 
string key, value; 

Грубо говоря (и, если у меня не было статической типизации) Я хочу сделать:

dict.TryGetValue(key, out value); 

, но это, очевидно, не будет компилироваться, так как он «не может конвертировать из«из string 'to' out object '".

Обойти я использую:

object valueAsObject; 
dict.TryGetValue(key, out valueAsObject); 
value = (string) valueAsObject; 

, но это кажется довольно неудобно.

Есть ли какая-либо языковая функция, позволяющая мне отбрасывать параметр в вызове метода, поэтому для меня этот переключатель для меня? Я не могу понять какой-либо синтаксис, который поможет, и я не могу ничего найти с Google.

ответ

2

Если вы знаете, что все значения являются строками, используйте вместо этого Dictionary<string, string>. Тип параметра out задается типом второго типичного параметра типа. Поскольку ваш объект в настоящее время является объектом, он возвращает объект при извлечении из словаря. Если вы измените его на строку, он вернет строки.

+4

Словарь предоставляется интерфейсом, который я использую. Я знаю, что все значения являются строками для моего использования, потому что это то, что я заполняю здесь. – Ken

0

Нет, вы не можете. Код внутри метода напрямую модифицирует переданную ему переменную, он не передает копию содержимого переменной.

2

Нет, нет никакого способа обойти это. Параметр out должен иметь переменную, которая точно соответствует.

Использование ссылки на строку небезопасно, так как словарь может содержать другие вещи, кроме строк. Однако, если у вас есть словарь строк и вы пытаетесь использовать объектную переменную в вызове TryGetValue, это не сработает, даже если это будет безопасно. Тип переменной должен точно соответствовать.

18

Я не знаю, если это отличная идея, но вы можете добавить общий метод расширения:

static bool TryGetTypedValue<TKey, TValue, TActual>(
     this IDictionary<TKey, TValue> data, 
     TKey key, 
     out TActual value) where TActual : TValue 
    { 
     TValue tmp; 
     if (data.TryGetValue(key, out tmp)) 
     { 
      value = (TActual)tmp; 
      return true; 
     } 
     value = default(TActual); 
     return false; 
    } 
    static void Main() 
    { 
     Dictionary<string,object> dict 
      = new Dictionary<string,object>(); 
     dict.Add("abc","def"); 
     string key = "abc", value; 
     dict.TryGetTypedValue(key, out value); 
    } 
+0

Это интересный бит синтаксического сахара. –

+0

+1 никогда не делал этого в словаре, но имел некоторые очень похожие вспомогательные методы. –

+1

Единственное, что я, возможно, подумал бы об изменении, - это обработка случая, когда значение найдено, но имеет неправильный тип. Вместо того, чтобы бросать, я мог бы просто вернуть false. Опять же, я не могу. Я должен подумать об этом, но стоит упомянуть. –

2

Я использовал метод расширения Марка, но добавил немного к нему.

Моя проблема с оригиналом заключалась в том, что в некоторых случаях мой словарь будет содержать int64, тогда как я ожидаю int 32. В других случаях словарь будет содержать строку (например, «42»), в то время как я хотел бы получить это как int.

Там нет никакого способа для обработки преобразования в методе Марка, так что я добавил возможность передать в делегат метода преобразования:

internal static bool TryGetTypedValue<TKey, TValue, TActual>(
     this IDictionary<TKey, TValue> data, 
     TKey key, 
     out TActual value, Func<TValue, TActual> converter = null) where TActual : TValue 
    { 
     TValue tmp; 
     if (data.TryGetValue(key, out tmp)) 
     { 
      if (converter != null) 
      { 
       value = converter(tmp); 
       return true; 
      } 
      if (tmp is TActual) 
      { 
       value = (TActual) tmp; 
       return true; 
      } 
      value = default(TActual); 
      return false; 
     } 
     value = default(TActual); 
     return false; 
    } 

Что вы можете назвать так:

int limit; 
myParameters.TryGetTypedValue("limitValue", out limit, Convert.ToInt32) 
Смежные вопросы