Можно ли перегрузить Funcи Funcимея такое же имя? - PullRequest
3 голосов
/ 26 февраля 2012

Прежде всего, я знаю, что могу просто определить два перегруженных вспомогательных метода, чтобы делать то, что мне нужно (или даже просто определить два Func <> с разными именами), но они используются только одним открытым методом, поэтому я ' m изучает способы определения двух локальных функций Functions <>, которые также перегружаются с использованием одного и того же имени. Взять, к примеру:

string DisplayValue(int value)
{ return DisplayValue(value, val => val.ToString()); }

string DisplayValue(int value, Func<int, string> formatter)
{ return (value < 0) ? "N/A" : formatter(value); }

Мне нужно многократно вызывать одну или другую версию в моем публичном методе для пользовательского форматирования специальных значений, поэтому я подумал, что могу "перевести" вышеприведенное в нечто вроде этого:

Func<int, Func<int, string>, string> displayValue =
    (value, formatter) => (value < 0) ? "N/A" : formatter(value);

Func<int, string> displayValue =
    value => displayValue(value, val => val.ToString());

Даже когда я печатал его, я знал, что не могу объявить два идентификатора делегата с одинаковыми именами, даже если они разных типов. Это более академично, чем то, что я полностью настроен на достижение перегрузок с помощью Func <>, но я думаю, они просто не могут сделать все, верно?

И я думаю, что вы не можете сделать что-то подобное, либо:

Func<string, params object[], string> formatArgs =
    (format, args) => string.Format(format, args);

Ответы [ 4 ]

6 голосов
/ 26 февраля 2012

Нет, вы не можете перегрузить переменные.Что ты и пытаешься сделать.

Это просто следует из случая использования:

 DisplaywWithoutFormatter(displayValue);
 DisplaywWithFormatter(displayValue);

Поскольку параметры не задействованы, компилятор не может их надежно различить.

1 голос
/ 26 февраля 2012

Вы можете явно определить тип делегата для случая с функцией String.Format ():

delegate string FormatDelegate(string formatString, params object[] @params);

Для .Net Framework с необязательными параметрами вы можете использовать ответ из @ Douglas.

Но если вы используете .Net Framework 3.5 (без дополнительных параметров), вы можете определить делегат DisplayValue следующим образом:

delegate string DisplayDelegate(int value, params Func<int, string>[] formatters);

Вот пример использования делегатов:

delegate string DisplayDelegate(int value, params Func<int, string>[] formatters);

delegate string FormatDelegate(string formatString, params object[] @params);

static void Main()
{
    FormatDelegate formatDelegate = (format, args) => string.Format(format, args);

    Console.WriteLine(formatDelegate("String with params: {0} {1}", 1, "something")); 
    //Output: "String with params: 1 something"

    Console.WriteLine(formatDelegate("String without params"));  
    //Output: "String without params"

    DisplayDelegate displayValue  = 
        (value, formatter) =>
            formatter.Length == 0 
                ? value.ToString() 
                : value < 0 
                    ? "N/A" 
                    : formatter[0](value);

    Console.WriteLine(displayValue(33));                         // "33"
    Console.WriteLine(displayValue(33, v => v.ToString("D4")));  // "0033"
    Console.WriteLine(displayValue(-33));                        // "-33"  
    Console.WriteLine(displayValue(-33, v => v.ToString("D4"))); // "N/A"
}
1 голос
/ 26 февраля 2012

Вы можете достичь желаемого, объявив делегата с необязательным аргументом для форматера:

delegate string DisplayValue(int value, Func<int, string> formatter = null);

static void Main(string[] args)
{
    DisplayValue displayValue = (value, formatter) =>
        formatter == null ?
            value.ToString() :
        value < 0 ?
            "N/A" :
            formatter(value);

    string s1 = displayValue(33);
    string s2 = displayValue(33, i => i.ToString("D4"));

    // s1: "33"
    // s2: "0033"
}
0 голосов
/ 26 февраля 2012

Я думаю, что вы можете сделать что-то подобное в C ++, создав функтор с перегруженным operator(). Но в C # у вас есть только делегаты, и они не могут быть перегружены.

...