Вопрос о неоднозначных звонках в C#
У меня есть вопрос, который на самом деле не проблема, но что-то, что сделало меня немного любопытным.
У меня есть класс с двумя методами. Один является статическим методом, а другой - методом экземпляра. Методы имеют одинаковое имя.
public class BlockHeader
{
public static BlockHeader Peek(BinaryReader reader)
{
// Create a block header and peek at it.
BlockHeader blockHeader = new BlockHeader();
blockHeader.Peek(reader);
return blockHeader;
}
public virtual void Peek(BinaryReader reader)
{
// Do magic.
}
}
Когда я пытаюсь построить свой проект, я получаю сообщение об ошибке:
Вызов неоднозначен между следующими методами или свойствами: "MyApp.BlockHeader.Peek(System.IO.BinaryReader)" и "MyApp.BlockHeader.Peek(System.IO.BinaryReader)"
Я знаю, что сигнатуры методов практически одинаковы, но я не понимаю, как я мог бы вызвать статический метод непосредственно из члена экземпляра.
Я предполагаю, что для этого есть очень веская причина, но кто-нибудь знает, что это за причина?
3 ответа
Общая политика дизайна C# состоит в том, чтобы заставить вас указывать, где есть потенциальная неопределенность. Перед лицом инструментов рефакторинга, которые позволяют заново настроить, статичны ли вещи или нет, эта позиция великолепна - особенно в таких случаях. Вы увидите много других подобных случаев (переопределение виртуальных, новые для теневого копирования и т. Д.).
В общем, устранение такого типа путаницы сделает код более понятным и заставит вас поддерживать порядок в своем доме.
РЕДАКТИРОВАТЬ: хороший пост от Эрика Липперта обсуждает еще одну причину этой двусмысленности, ведущей к ошибке, которую вы видели
Вот выдержка из спецификации языка C# 3.0.
Сигнатура метода должна быть уникальной в классе, в котором объявлен метод. Сигнатура метода состоит из имени метода, количества параметров типа и числа, модификаторов и типов его параметров. Сигнатура метода не включает тип возвращаемого значения.
Модификатор "static" не является частью подписи, поэтому ваш пример нарушает это правило уникальных подписей.
Я не знаю причину этого правила.
Я думаю, что нет технической причины, чтобы это запретить, но это делается для того, чтобы защитить программиста от самого себя. Рассмотрим следующий пример:
public static void Main()
{
BlockHeader BlockHeader = new BlockHeader();
BlockHeader.Peek();
}
Приведенный выше пример вполне допустим, но если бы описанная вами ситуация была разрешена, она была бы удобочитаемой? Не могли бы вы в мгновение ока увидеть, был ли вызван метод экземпляра или статический метод?