Вычисление параметров С#?
Можно ли изгнать аргументы param в С#? У меня есть:
Dictionary<string,object> dict; // but I know all values are strings
string key, value;
Грубо говоря (и если у меня не было статического набора текста), я хочу сделать:
dict.TryGetValue(key, out value);
но это, очевидно, не будет компилироваться, потому что он "не может преобразовать из" out string "в" out object "".
Обходной путь, который я использую, это:
object valueAsObject;
dict.TryGetValue(key, out valueAsObject);
value = (string) valueAsObject;
но это кажется довольно неудобным.
Есть ли какая-либо языковая функция, позволяющая мне отбрасывать параметр out в вызове метода, поэтому он делает это для меня? Я не могу понять какой-либо синтаксис, который поможет, и я не могу ничего найти с Google.
Ответы
Ответ 1
Я не знаю, отличная идея, но вы можете добавить общий метод расширения:
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);
}
Ответ 2
Если вы знаете, что все значения имеют значения, используйте Dictionary<string, string>
. Тип параметра out задается типом второго типичного параметра типа. Поскольку ваш объект в настоящее время является объектом, он возвращает объект при извлечении из словаря. Если вы измените его на строку, он вернет строки.
Ответ 3
Нет, нет никакого способа обойти это. Параметр out должен иметь переменную, которая точно соответствует.
Использование строковой ссылки небезопасно, поскольку словарь может содержать другие вещи, кроме строк. Однако, если у вас есть словарь строк и вы пытаетесь использовать объектную переменную в вызове TryGetValue, это не сработает, даже если это будет безопасно. Тип переменной должен точно соответствовать.
Ответ 4
Я использовал метод расширения Marc, но добавил немного к нему.
Моя проблема с оригиналом заключалась в том, что в некоторых случаях мой словарь будет содержать int64, тогда как я ожидаю int 32. В других случаях словарь будет содержать строку (например, "42" ), в то время как я хотел бы ее получить как int.
Невозможно обработать преобразование в методе Marc, поэтому я добавил возможность передать делегат методу преобразования:
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)
Ответ 5
Нет, вы не можете. Код внутри метода напрямую изменяет переданную ему переменную, он не передает копию содержимого переменной.