Я заметил, что с необязательными параметрами в 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 для внедрения конкретного класса), то на самом деле нет точка, имеющая значение по умолчанию, так как вызывающая сторона должна всегда предоставлять его в любом случае.
MyInterface
и вызвать его с дополнительным параметром:((MyInterface)obj).TestMethod();
.Ответы:
ОБНОВЛЕНИЕ: Этот вопрос был темой моего блога 12 мая 2011 года. Спасибо за отличный вопрос!
Предположим, у вас есть интерфейс, который вы описываете, и сотня классов, которые его реализуют. Затем вы решаете сделать один из параметров одного из методов интерфейса необязательным. Вы предполагаете, что правильно сделать, чтобы компилятор заставил разработчика найти каждую реализацию этого метода интерфейса, а также сделать параметр необязательным?
Предположим, мы сделали это. Теперь предположим, что у разработчика не было исходного кода для реализации:
Как автор D должен сделать эту работу? Обязаны ли они в вашем мире позвонить автору B по телефону и попросить его отправить им новую версию B, в которой метод имеет необязательный параметр?
Это не будет летать. Что делать, если два человека позвонят автору B, и один из них хочет, чтобы значение по умолчанию было истинным, а один из них хотел бы, чтобы оно было ложным? Что если автор Б просто отказывается подыгрывать?
Возможно, в этом случае они должны будут сказать:
Предлагаемая функция, кажется, добавляет много неудобств для программиста без соответствующего увеличения представительной мощности. В чем преимущество этой функции, которая оправдывает повышенную стоимость для пользователя?
ОБНОВЛЕНИЕ: В комментариях ниже, суперкат предлагает языковую особенность, которая действительно добавила бы мощности в язык и включила бы некоторые сценарии, подобные описанному в этом вопросе. К вашему сведению, эта функция - реализация методов по умолчанию в интерфейсах - будет добавлена в C # 8.
источник
Необязательный параметр просто помечается атрибутом. Этот атрибут указывает компилятору вставить значение по умолчанию для этого параметра на сайте вызова.
Вызов
obj2.TestMethod();
заменяется на то,obj2.TestMethod(false);
когда код C # компилируется в IL, а не во время JIT.Таким образом, всегда вызывающая сторона предоставляет значение по умолчанию с необязательными параметрами. Это также имеет последствия для двоичного управления версиями: если вы измените значение по умолчанию, но не перекомпилируете вызывающий код, он продолжит использовать старое значение по умолчанию.
Вы уже не можете сделать это, если метод интерфейса был реализован явно .
источник
Поскольку параметры по умолчанию разрешаются во время компиляции, а не во время выполнения. Таким образом, значения по умолчанию относятся не к вызываемому объекту, а к ссылочному типу, через который он вызывается.
источник
Необязательные параметры напоминают подстановку макросов из того, что я понимаю. Они не являются действительно необязательными с точки зрения метода. Артефактом этого является поведение, которое вы видите, когда вы получаете разные результаты, если переходите к интерфейсу.
источник