"не может реализовать ошибку интерфейса", когда интерфейс и бетон находятся в разных проектах - программирование
Подтвердить что ты не робот

"не может реализовать ошибку интерфейса", когда интерфейс и бетон находятся в разных проектах

Это компилируется:

public interface IMyInterface
{
    event Action<dynamic> OnSomeEvent;
}

class MyInterface : IMyInterface
{
    public event Action<dynamic> OnSomeEvent;
}

Но когда я разделяю интерфейс и реализацию на разные проекты, я получаю:

Accessor 'TestProject2.MyInterface.OnSomeEvent.remove' не может реализовать интерфейс 'InterfaceNamespace.IMyInterface.remove_OnSomeEvent (System.Action)' для типа "TestProject2.MyInterface". Использовать явный интерфейс реализация.

Это происходит только с динамическим параметром...

4b9b3361

Ответ 1

Хорошая добыча. Это похоже на ошибку в компиляторе С# - я буду пинговать Эрика Липперта, чтобы посмотреть, что он думает. (dynamic может быть немного сложным, вполне может быть совершенно хорошая, но неочевидная причина этой ошибки.)

EDIT: Код ниже, похоже, не работает. Я мог бы поклясться, что у меня было это сегодня утром... Я очень смущен, что происходит. По словам Саймона, код выходит из строя с сообщением о том, что он не поддерживается языком.

Обратите внимание, что если вы используете явную реализацию интерфейса, она, похоже, просто компилируется:

// Doesn't actually compile - see edit above
class MyInterface : IMyInterface
{
    private Action<dynamic> foo;

    event Action<dynamic> IMyInterface.OnSomeEvent
    {
        // TODO (potentially): thread safety
        add { foo += value; }
        remove { foo -= value; }
    }
}

EDIT: Остальная часть этого ответа по-прежнему стоит...

Обратите внимание, что вы не можете указать полевое событие как явно реализованное событие, то есть это не работает:

event Action<dynamic> IMyInterface.OnSomeEvent;

Появляется следующее сообщение об ошибке:

Test.cs(15,39): ошибка CS0071: Явная реализация интерфейса для события должна использовать синтаксис доступа к событиям

И если вы просто попытаетесь изменить синтаксис доступа к событию, вы получите ту же ошибку, что и оригинальный код.

Обратите внимание, что изменение события в свойство отлично работает с реализацией реализованного автоматически.

Ответ 2

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

В будущем подумайте о публикации таких вещей на Connect.microsoft.com; который быстрее добирается до тестировщиков и дает нам лучший механизм для получения дополнительной информации о проблеме.

Ответ 3

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

Я проверил несколько вещей, этот интерфейс:

namespace DifferentAssemblyNamespace
{
    public interface IBar
    {
        event Action<dynamic> OnSomeEvent;
    }
}

и его реализация:

// implicit interface implementation
// generates compile error "Explicit interface implementation"
public class Foo1 : IBar
{
    private Action<dynamic> foo;
    public event Action<dynamic> OnSomeEvent
    {
        add { foo += value; }
        remove { foo -= value; }
    }
}

// implicit interface implementation
// generates compile error "Not supported by the language"
public class Foo2 : IBar
{
    private Action<dynamic> foo;

    event Action<dynamic> IBar.OnSomeEvent
    {
        add { foo += value; }
        remove { foo -= value; }
    }
}

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

, но.., если мы вызываем generics для справки и используем параметр Тип вместо того, чтобы использовать dynamic прямо как:

namespace DifferentAssemblyNamespace
{
    public interface IGenericBar<T>
    {
        event Action<T> OnSomeEvent;
    }
}

и его реализации.

// implicit interface implementation
public class Foo3<T> : IGenericBar<T>
{
    private Action<T> foo;

    event Action<T> IGenericBar<T>.OnSomeEvent
    {
        add { foo += value; }
        remove { foo -= value; }
    }
}

по какой-то причине мы можем построить (как следует) и запустить:

/** does build **/
IGenericBar<dynamic> f = new Foo3<dynamic>();
f.OnSomeEvent += new Action<dynamic>(f_OnSomeEvent);

похоже, что параметр типа делает что-то дополнительное, что компилятор доволен.

Я не уверен, что происходит, поэтому я тоже хотел бы знать.

предположение, очень гипотетическое (возможно, дерьмо)

но в настоящее время я ставлю свои два цента на сравнение типов должно быть с помощью аксессуаров add/remove в связанный список, который содержит цель/методы события.

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

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

/предположение, очень гипотетическое (возможно, дерьмо)