2

One more question from the series "why does VisualStudio not support this code?"...

Given an overloaded function

private string ConfigQuery(string username) {
    return "A";
}
private string ConfigQuery(int configId) {
    return "B";
}

the following code is not possible:

public Config ConfigAPI(int id=0) {
    string s = ConfigQuery(id==0?User.Identity.Name:id);
}

but the code

public Config ConfigAPI(int id=0) {
    string s = (id==0?ConfigQuery(User.Identity.Name):ConfigQuery(id));
}

is. Is this reasonable behaviour? Then why would I use an overloaded function at all, instead of giving them more appropriate names like UserNameConfigQuery, ConfigIdConfigQuery?

Community
  • 1
  • 1
Alexander
  • 19,906
  • 19
  • 75
  • 162

4 Answers4

2

Yes, this is reasonable behavior.

Remember that the overload to call is determined at compile time vs. runtime. id==0? will not be evaluated until runtime of course.

You might still want to use overloads for:

  • same operations for different types (e.g. myString.Replace('1', '5') vs. myString.Replace("1", "5")) instead of using generics
  • optional/default params (e.g. new Foo(bar) vs. new Foo(bar, baz) or myRegex.Replace("blah", "yada") vs. myRegex.Replace("blah", "yada", 2)) instead of formal support that C# has added for optional and default parameters where they may make sense too

Also, IntelliSense, code documentation, and (formal or navigational) searches will help a lot less with differently-named methods that really do (nearly) the same thing, just differ on type or number of parameters. For example, consider finding and understanding the (near-)sameness of:

  • QueryConfig(string username) and QueryConfig(int configId) using overloads versus UserNameConfigQuery(string username) and ConfigIdConfigQuery(int configId) using "more appropriate" names
  • Replace(string input, string replacement) and Replace(string input, string replacement, int count) using overloads versus CountRestrictedReplace(string input, string replacement, int count) and UnrestrictedReplace(string input, string replacement) using "more appropriate" names
Community
  • 1
  • 1
J0e3gan
  • 8,740
  • 10
  • 53
  • 80
2

Overloading is resolved at compile time, not at run time. The ternary operator ?: is evaluated at runtime. So at compile time, compiler doesn't know which function overload to link to as it doesn't know if id==0 or not. That's why your second example works because which overload called there can be resolved at compile time.

The reason for overloading is convenience of calling the same logical function with different number or type of parameters.

LB2
  • 4,802
  • 19
  • 35
  • 1
    That being said, you could of course let the overloading resolve at runtime by using `dynamic` like `ConfigQuery(id==0?(dynamic)User.Identity.Name:id)` – sloth Mar 20 '14 at 15:14
2

Generally speaking, with a few exceptions such as the use of reflection, you are correct, there really isn't any "functionality" in overloading a method as opposed to creating a new method with a different name entirely. This is because, as has already been said, overload resolution is done at compile time (again, there are a few rare exceptions to this which should, generally speaking, be avoided) rather than at run time.

So you really aren't gaining anything, in terms of functionality, over giving each method a different name. It's mostly for convenience as a programmer, and to make it clear to users of your type that the method does the same thing, it just does it using one of several options.

Servy
  • 202,030
  • 26
  • 332
  • 449
1

You did not post the error you got, but by the look of it the failure has nothing to do with overloading.

The error is because the ternary operator ? cannot get a string and int arguments, they need to be of the same type or with an implicit cast between them.

this post explains it rather well.

Edit:
From the spec, you can understand the reason for the failure:

If x has type X and y has type Y then:

  • If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.

  • If an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.

  • Otherwise, no expression type can be determined, and a compile-time error occurs.

Community
  • 1
  • 1
Avi Turner
  • 10,234
  • 7
  • 48
  • 75