Литье C # out параметров? - PullRequest
       32

Литье C # out параметров?

22 голосов
/ 28 августа 2009

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

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.

Ответы [ 5 ]

20 голосов
/ 28 августа 2009

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

    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);
    }
3 голосов
/ 07 июля 2016

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

Моя проблема с оригиналом состояла в том, что в некоторых случаях мой словарь содержал бы 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)
2 голосов
/ 28 августа 2009

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

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

2 голосов
/ 28 августа 2009

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

1 голос
/ 28 августа 2009

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

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