Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# optional parameters: Why can I define the default different on interface and derived class?

Tags:

With C#, we now can have optional parameters, and give them default values like this:

public abstract class ImporterBase : IImporter {
    public void ImportX(bool skipId = true) {
        //....
    }
}

Now, suppose in the interface we derive from, we have

public interface IImporter {
    void ImportX(bool skipId = false);
}

See, that the default value is defined as different in the base class as in the interface. This is really confusing, as now the default value depends whether I do

IImporter interfaceImporter = new myConcreteImporter(); //which derives from ImporterBase
interfaceImporter.DoX(); //skipId = false

or

ImporterBase concreteImporter = new myConcreteImporter(); //which derives from ImporterBase
concreteImporter.DoX(); //skipId = true

Why is it allowed to define the default value differently in both the interface and the derived class?

Note: this question similar, but focuses on the optionality, not on the value.

like image 333
Marcel Avatar asked Jan 09 '20 13:01

Marcel


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.


1 Answers

To clarify, I'm interpreting the question to be:

If a method is defined in an interface / base class which has a method which has a parameter with a default value, and a class implements / overrides that method but provides a different default value, why doesn't the compiler warn?

Note that this doesn't cover the case where the implementation doesn't provide any default value -- that case is explained by Eric Lippert.


I asked this on the csharplang gitter channel, and the response from someone who has been heavily involved in the language design for a long time was:

i think an analyzer sounds very good for this.

From that, and the other links posted here (which don't even mention this specific case), my best guess is that this specific case just wasn't considered, or was briefly considered but dismissed as too niche. Of course, once C# 4 was released, there was no way to add a compiler error or warning without breaking backwards compatibility.

You could write an analyzer which catches this case (which had a code fix to correct the default value), and try to get it incorporated into Roslyn.


As a footnote, there are a few cases I can see which would cause issues.

An interface changes the default value for one of its parameters

This is already a binary-breaking change, and this would promote it to a source-breaking change.

Two interfaces with different default values

interface I1
{
    void Foo(bool x = false);
}
interface I2
{
    void Foo(bool x = true);
}
class C : I1, I2
{
   ...?
}

If you did want to specify a default value for C.Foo, this case could be solved by explicitly implementing one of the interfaces:

class C : I1, I2
{
    public void Foo(bool x = false) { ... }
    void I2.Foo(bool x) => Foo(x);
}

Alternatively you could just ignore this case, and not warn.

Adding an interface in a child class

interface I1
{
    void Foo(bool x = false);
}
class Parent
{
    public void Foo(bool x = true) { ... }
}
class Child : Parent, I1
{
    ...?
}

I'm not sure what an intuitive solution to this would be, but since it's so niche I'd be tempted just to ignore it, and not warn.

like image 192
canton7 Avatar answered Sep 30 '22 20:09

canton7