Вопрос о неоднозначных звонках в 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();
}

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

Другие вопросы по тегам