Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning From Explicitly Implementing an Interface with Optional Parameters

I was playing with optional parameters to see how they would work with interfaces and I came across a strange warning. The setup I had was the following code:

 public interface ITestInterface  {      void TestOptional(int a = 5, int b = 10, object c = null);  }   public class TestClass : ITestInterface  {       void ITestInterface.TestOptional(int a = 5, int b = 5, object c = null)      {         Console.Write("a=" + a + " b=" + b + " c=" + c);      }  } 

The compiler gives me the following warnings:

  • The default value specified for parameter 'a' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
  • The default value specified for parameter 'b' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
  • The default value specified for parameter 'c' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments

If I run this with the following code:

class Program {     static void Main(string[] args)     {         ITestInterface test = new TestClass();         test.TestOptional();         Console.ReadLine();     } } 

I get the output of "a=5 b=10 c=" as I'd expect.

My question is what is warning for? What contexts is it referring to?

like image 486
Craig Suchanec Avatar asked Apr 15 '11 22:04

Craig Suchanec


People also ask

Can we have optional parameter in interface?

When you call the method in the class you have to follow the class rules (the parameter is not optional in the class so you can't call the method without it), and in the second hand when you implement the interface you have to follow the interface rules,so you can override the methods with/without optional parameters.

What are optional parameters are added?

The definition of a method, constructor, indexer, or delegate can specify its parameters are required or optional. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters. Each optional parameter has a default value as part of its definition.

What is a optional parameter?

A method that contains optional parameters does not force to pass arguments at calling time. It means we call method without passing the arguments. The optional parameter contains a default value in function definition. If we do not pass optional argument value at calling time, the default value is used.


2 Answers

The problem with optional arguments in C# is whether the callee sees the object as a TestClass or an ITestInterface. In the first case, the values declared in the class apply. In the second case the values declared in the interface apply. It is because the compiler uses the statically available type information to construct the call. In case of an explicit interface implementation the method is never called 'for a class', always 'for an interface'

The C# Language Specification in 10.6.1 states:

If optional parameters occur in an implementing partial method declaration (§10.2.7) , an explicit interface member implementation (§13.4.1) or in a single-parameter indexer declaration (§10.9) the compiler should give a warning, since these members can never be invoked in a way that permits arguments to be omitted.

like image 149
Ondrej Tucny Avatar answered Oct 01 '22 09:10

Ondrej Tucny


The compiler is telling you

void ITestInterface.TestOptional(int a = 5, int b = 5, object c = null) 

Is fundamentally the same as

void ITestInterface.TestOptional(int a, int b, object c) 

The reason being, since you have to invoke TestOptional through the interface the interface will supply the parameters. There is no way at the class for you to have not been supplied a parameter value.

2020 edit: soon you will be able to do this with C# 8 by default implementations of interfaces

interface ILogger {     void Log(LogLevel level, string message);     void Log(Exception ex) => Log(LogLevel.Error, ex.ToString()); } 

You could just as easily do something akin to:

public interface ITestInterface {      void TestOptional(int a, int b, object c);       void TestOptional() => TestOptional(5);      void TestOptional(int a) => TestOptional(a, 10)      void TestOptional(int a, int b) => TestOptional(a, b, null);  } 
like image 22
Chris Marisic Avatar answered Oct 01 '22 10:10

Chris Marisic