#c# #c#-4.0
#c# #c #-4.0
Вопрос:
Рассмотрим следующее консольное приложение:
class Program
{
static void Main()
{
MyInterface test = new MyClass();
test.MyMethod();
Console.ReadKey();
}
}
interface MyInterface
{
void MyMethod(string myString = "I am the default value on the interface");
}
class MyClass : MyInterface
{
public void MyMethod(string myString = "I am the default value set on the implementing class")
{
Console.WriteLine(myString);
}
}
Результат этой программы является:
I am the default value on the interface
(1) Почему нет способа указать параметр как необязательный в интерфейсе без указания значения. Я считаю, что значением по умолчанию являются детали реализации. Если бы мы написали этот код в стиле предварительного необязательного параметра, мы бы создали две перегрузки в интерфейсе, а значение по умолчанию было бы указано в реализующем классе. Т.е. мы имели бы:
interface MyInterface
{
void MyMethod();
void MyMethod(string myString);
}
class MyClass : MyInterface
{
public void MyMethod()
{
MyMethod("I am the default value set on the implementing class");
}
public void MyMethod(string myString)
{
Console.WriteLine(myString);
}
}
Который выводит, как и следовало ожидать,
I am the default value set on the implementing class
(2) Почему мы не можем переопределить значение по умолчанию в реализующем классе!
Ответ №1:
Значения по умолчанию в .Net на самом деле представляет собой синтаксический сахар на основе компилятора. На сайте вызова компилятор добавляет для вас значения по умолчанию. Он не может знать тип среды выполнения вашего объекта во время компиляции, поэтому он должен вставить значение, определенное в интерфейсе.
Следовательно, они не могут быть «переопределены» в реализациях, потому что переопределять нечего.
Эрик Липперт написал очень интересную серию сообщений в блоге на тему необязательных аргументов, с первым из которых можно ознакомиться здесь.
Обновить
Из ваших комментариев следует, что вы предлагаете либо какую-то форму «виртуального» параметра (в котором объявляется тип среды выполнения), о котором среда CLR должна была бы «знать». Я предполагаю, что эта реализация была исключена из-за того, что затраты (проектирование, документирование, внедрение, тестирование и т.д.) Были слишком высоки по сравнению с преимуществами, которые она давала (хотя это только предположение!).). В качестве альтернативы существует опция метода делегирования по умолчанию, ie:
void M(bool y = false) { ... whatever ... }
Переписывается компилятором как:
void M() { M(false); }
void M(bool y) { ... whatever ... }
Но использование этого маршрута приводит к потенциально неприемлемому уровню перегрузок, как только принимается во внимание множество необязательных аргументов и именованных аргументов.
Комментарии:
1. Приветствую Рич, я вижу проблему. Не было бы более разумным для них добавить «необязательное» ключевое слово вместо того, чтобы указывать значение в интерфейсе? Для меня нет смысла указывать значение по умолчанию в интерфейсе.
Ответ №2:
1) В вашем мышлении есть недостаток. Вы говорите, что значение по умолчанию является деталью реализации. Интерфейсы не содержат деталей реализации. По этой логике указание значения по умолчанию действительно не относится к интерфейсу.
Просто напишите интерфейс, используя перегруженные методы. Определение не только станет более понятным, но и интерфейс станет более совместимым при взаимодействии с другими языками, и у вас не возникнет проблем с управлением версиями, связанных с необязательными параметрами.
2) Поскольку интерфейс определяет операционный контракт. Интерфейс говорит, что по умолчанию должно быть что-то…следовательно, класс должен реализовать это таким образом.
Комментарии:
1. (1) Действительно, я согласен, однако, если вы оставите это, вы получите предупреждение компилятора, потому что он не будет знать, что параметр является необязательным. Это приводит к моему вопросу (1) Почему вы не можете указать его как необязательный без указания значения?
2. @Tony Leeper — Также получил эту хорошую серию угловых примеров от Эрика Липперта через Twitter: blogs.msdn.com/b/ericlippert/archive/2011/05/09 /…