Реализация по умолчанию в интерфейсе не видна компилятору?

Вот мой код внутри проекта С #, который нацелен на.NET Core 3.0 (поэтому я должен быть на С # 8.0) с Visual Studio 2019 (16.3.9)

public interface IJsonAble
{
    public string ToJson() => System.Text.Json.JsonSerializer.Serialize(this);
}

public class SumRequest : IJsonAble
{
    public int X { get; set; }

    public int Y { get; set; }

    public void Tmp()
    {
        new SumRequest().ToJson(); //compile error
    }
}

Ошибка компиляции:

CS1061 SumRequest не содержит определения ToJson, и не может быть найден доступный метод расширения ToJson, принимающий первый аргумент типа SumRequest (вам не хватает директивы using или ссылки на сборку?)

Может ли кто-нибудь пролить свет на это поведение?

3 ответа

Решение

Методы доступны только в интерфейсе, но не в классе. Вместо этого вы можете сделать это:

IJsonAble request = new SumRequest()
var result = request.ToJson();

Или:

((IJsonAble)new SumRequest()).ToJson();

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

Попробуйте использовать (new SumRequest() as IJsonAble).ToJson(); чтобы немного помочь компилятору.

В любом случае, я уверен, что тебе нужно (this as IJsonAble).ToJson(), предполагая, что вы хотите применить ToJson к текущему экземпляру SumRequest.

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

      public static class JsonAbleExtensions {
    public static string ToJson(this IJsonAble jsonAble)
    {
        return jsonAble.ToJson();
    }
}

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

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