3

First of all, I know I can just define two overloaded helper methods to do what I need (or even just define two Func<>s with different names), but these are only used by one public method, so I'm exploring ways to define two local Func<>s that also overload by using the same name. Take, for example:

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); }

I need to call one or the other version many times in my public method to custom format special values, so I thought I could "translate" the above into something like this:

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());

Even as I was typing it I knew I couldn't declare two delegate identifiers having the same name, even if they are different types. This is more academic than me being dead set on achieving overloads using Func<>s, but I guess they just can't do everything, right?

And I guess you can't do something like this, either:

Func<string, params object[], string> formatArgs =
    (format, args) => string.Format(format, args);
Erhhung
  • 967
  • 9
  • 14
  • 1
    Have you tried creating a custom delegate with a `params` arg? `public delegate string StringFormatter(string format, params string[] args);` ? – Marc Gravell Feb 26 '12 at 12:58

4 Answers4

6

No, you cannot overload variables. Which is what you are trying to do.

It follows simply from the usage case:

 DisplaywWithoutFormatter(displayValue);
 DisplaywWithFormatter(displayValue);

Since there are no parameters involved the compiler cannot reliably distinguish between the two.

H H
  • 263,252
  • 30
  • 330
  • 514
1

You could achieve what you want by declaring a delegate with an optional argument for the formatter:

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"
}
Douglas
  • 53,759
  • 13
  • 140
  • 188
1

You can explicitly define delegate type for the case with String.Format() function:

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

For the .Net Framework with optional parameters you can use answer from @Douglas.

But if you use .Net Framework 3.5 (without optional parameters) then you can define DisplayValue delegate like this:

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

Here is a sample of using the delegates:

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"
}
olegaz
  • 86
  • 1
  • 4
0

I think you could do something like this in C++ by creating a functor with overloaded operator(). But in C#, you have only delegates and they can't be overloaded.

svick
  • 236,525
  • 50
  • 385
  • 514