Почему необязательные параметры C # 4, определенные в интерфейсе, не применяются в классе реализации? - PullRequest
343 голосов
/ 07 февраля 2011

Я заметил, что с необязательными параметрами в C # 4, если вы указываете параметр как необязательный для интерфейса, вам НЕ нужно делать этот параметр необязательным для любого реализующего класса:

public interface MyInterface
{
    void TestMethod(bool flag = false);
}

public class MyClass : MyInterface
{
    public void TestMethod(bool flag)
    {
        Console.WriteLine(flag);
    }
}

и, следовательно:

var obj = new MyClass();        
obj.TestMethod(); // compiler error

var obj2 = new MyClass() as MyInterface;
obj2.TestMethod(); // prints false

Кто-нибудь знает, почему дополнительные параметры предназначены для такой работы?

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

С другой стороны, это отключение означает, что вы не всегда можете использовать конкретный класс и интерфейс взаимозаменяемо. Это, конечно, не будет проблемой, если в реализации указано значение по умолчанию, но если вы представляете конкретный класс в качестве интерфейса (например, с помощью некоторой инфраструктуры IOC для внедрения конкретного класса), то на самом деле нет точка, имеющая значение по умолчанию, так как вызывающая сторона должна всегда указывать его.

Ответы [ 4 ]

225 голосов
/ 07 февраля 2011

ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога 12 мая 2011 года. Спасибо за отличный вопрос!

Предположим, у вас есть интерфейс, который вы описываете, и сотня классов, которыереализовать это.Затем вы решаете сделать один из параметров одного из методов интерфейса необязательным.Вы предполагаете, что правильно сделать, чтобы компилятор заставил разработчика найти каждую реализацию этого метода интерфейса и сделать параметр также необязательным?

Предположим, мы это сделали.Теперь предположим, что у разработчика не было исходного кода для реализации:


// in metadata:
public class B 
{ 
    public void TestMethod(bool b) {}
}

// in source code
interface MyInterface 
{ 
    void TestMethod(bool b = false); 
}
class D : B, MyInterface {}
// Legal because D's base class has a public method 
// that implements the interface method

Как автор D должен сделать эту работу?Обязаны ли они в вашем мире позвонить автору B по телефону и попросить его отправить им новую версию B, в которой метод имеет необязательный параметр?

Это не полетит.Что если два человека позвонят автору B, и один из них хочет, чтобы значение по умолчанию было истинным, а один из них хотел бы, чтобы оно было ложным?Что, если автор B просто отказывается подыгрывать?

Возможно, в этом случае они должны будут сказать:

class D : B, MyInterface 
{
    public new void TestMethod(bool b = false)
    {
        base.TestMethod(b);
    }
}

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

46 голосов
/ 07 февраля 2011

Необязательный параметр просто помечен атрибутом.Этот атрибут указывает компилятору вставить значение по умолчанию для этого параметра на сайте вызова.

Вызов obj2.TestMethod(); заменяется на obj2.TestMethod(false);, когда код C # компилируется в IL, а не в JIT-.time.

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

С другой стороны, это отключение означает, что выне всегда можно использовать конкретный класс и интерфейс взаимозаменяемо.

Вы уже не можете сделать это, если метод интерфейса реализован явно .

27 голосов
/ 07 февраля 2011

Поскольку параметры по умолчанию разрешаются во время компиляции, а не во время выполнения.Поэтому значения по умолчанию относятся не к вызываемому объекту, а к ссылочному типу, через который он вызывается.

5 голосов
/ 07 февраля 2011

Необязательные параметры напоминают подстановку макросов из того, что я понимаю.Они не являются действительно необязательными с точки зрения метода.Артефактом этого является поведение, которое вы видите, когда вы получаете разные результаты, если вы применяете интерфейс.

...