Реализация по умолчанию в интерфейсе не видна компилятору?
Вот мой код внутри проекта С #, который нацелен на.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();
}
}
Это позволяет избежать использования явного приведения типов во время выполнения или принуждения пользователей интерфейса реализовывать метод вручную для всех классов, которые наследуются от него.