Подтвердить что ты не робот

Предупреждение от явного внедрения интерфейса с дополнительными параметрами

Я играл с дополнительными параметрами, чтобы увидеть, как они будут работать с интерфейсами, и я столкнулся с странным предупреждением. У меня был следующий код:

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

Компилятор дает мне следующие предупреждения:

  • Значение по умолчанию, указанное для параметра 'a', не будет иметь эффекта, поскольку оно применяется к члену, который используется в контекстах, которые не позволяют необязательные аргументы
  • Значение по умолчанию, указанное для параметра 'b', не будет иметь эффекта, поскольку оно применяется к члену, который используется в контекстах, которые не позволяют необязательные аргументы
  • Значение по умолчанию, указанное для параметра 'c', не будет иметь эффекта, поскольку оно применяется к члену, который используется в контекстах, которые не позволяют необязательные аргументы

Если я запустил это со следующим кодом:

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

Я получаю вывод "a=5 b=10 c=", как я ожидал.

Мой вопрос - это предупреждение? В каких контекстах это относится?

4b9b3361

Ответ 1

Проблема с необязательными аргументами в С# заключается в том, видит ли вызывающий объект объект как TestClass или ITestInterface. В первом случае применяются значения, объявленные в классе. Во втором случае применяются значения, объявленные в интерфейсе. Это связано с тем, что для построения вызова компилятор использует статически доступную информацию о типе. В случае явной реализации интерфейса этот метод никогда не называется "для класса", всегда "для интерфейса"

Спецификация языка С# в 10.6.1 гласит:

Если в объявлении частичного метода реализации (§10.2.7) имеются необязательные параметры, явная реализация элемента интерфейса (§13.4.1) или в однопараметрическом объявлении индексатора (§10.9), компилятор должен дать предупреждение, поскольку эти члены никогда не могут быть вызваны таким образом, чтобы разрешить аргументы.

Ответ 3

Craig,

Эти предупреждения поступают из значений по умолчанию, указанных в реализации метода класса. В .net значение по умолчанию для аргумента всегда определяется ссылочным типом. И, конечно, с явной реализацией интерфейса, как это, можно вызвать этот метод только через ссылку на интерфейс, которая определяет значение по умолчанию. Как таковой, конечно, не имеет значения, какое значение вы ставите здесь в классе, поскольку он никогда не будет разрешен, и вы можете легко его удалить. Intellisense будет прекрасным, учитывая, что значение по умолчанию здесь никогда не может быть эффективным.

http://funcakes.posterous.com/?tag=c

http://funcakes.posterous.com/c-40-optional-parameters-default-values-and-i

Ответ 4

Компилятор сообщает вам

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

В принципе это то же самое, что

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

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