Определение неявных и явных бросков для интерфейсов C#

Существует ли способ написать основанный на интерфейсе код (т.е. использующие интерфейсы, а не классы как типы, принятые и розданные) в C#, не бросая использование вещей как неявные броски? Вот некоторый пример кода - было много удалено, но это соответствующие части.

 public class Game
 {
     public class VariantInfo
     {
         public string Language { get; set; }
         public string Variant { get; set; }
     }
 }

И в ScrDictionary.cs, мы имеем...

 public class ScrDictionary: IScrDictionary
 {
     public string Language { get; set; }
     public string Variant { get; set; }

     public static implicit operator Game.VariantInfo(ScrDictionary s)
     {
        return new Game.VariantInfo{Language=sd.Language, Variant=sd.Variant};
     }
 }

И интерфейс...

 public interface IScrDictionary
 {
     string Language { get; set; }
     string Variant { get; set; }
 }

Я хочу смочь использовать IScrDictionary вместо ScrDictionary, но все еще смочь неявно преобразовать a ScrDictionary к a Game.VariantInfo. Кроме того, в то время как может быть простой способ сделать эту работу путем предоставления IScrDictionary свойство типа Game.VariantInfo мой вопрос в более общем плане: существует ли способ определить броски или оператор, перегружающийся в интерфейсах? (В противном случае, что надлежащий путь C# состоит в том, чтобы поддержать эту функциональность, не бросая ориентированный на интерфейс на дизайн?)

21
задан ehdv 5 May 2010 в 19:32
поделиться

1 ответ

Вы не можете определять приведения или перегрузку операторов в интерфейсах. Поскольку интерфейс - это контракт, описывающий члены, которые всегда будут доступны (либо как явное приведение к этому интерфейсу, либо как публичные члены), и ничего более, вы не можете полагаться на то, что интерфейсы содержат какую-либо встроенную логику, например, как приводить или как операторы будут работать с этим интерфейсом.

Вы можете наследоваться от абстрактного базового класса, который реализует интерфейс и предоставляет логику, необходимую для приведения или перегрузки операторов. Это не нарушает дизайн, ориентированный на интерфейс. Классы, которые не наследуются от общего базового класса, но реализуют интерфейс, все равно должны будут самостоятельно реализовывать свои собственные неявные приведения и перегрузки операторов. Если вы хотите централизовать логику работы с классами, реализующими общий интерфейс, вы можете сделать это в C# 3.0+/.NET Fx 3.5 с помощью методов расширения (или в предыдущих версиях с помощью статических методов). Ниже я демонстрирую это на примере класса-утилиты и двух классов, Foo и Bar, которые не имеют общего предка. Они разделяют код, который включает в себя утилитарную функцию Add, поэтому вам не нужно повторять эту реализацию в обоих классах.

public interface IInterface
{
    int X { get; set; }
    int Y { get; set; }
}

public static class IInterfaceTHelper
{
    public static IInterface Add<T>(this IInterface a, IInterface b) 
        where T : new()
    {
        var ret = (IInterface)new T();
        ret.X = a.X + b.X;
        ret.Y = a.Y + b.Y;
        return ret;
    }
}

class Foo : IInterface
{
    public int X { get; set; }
    public int Y { get; set; }

    public static IInterface operator +(Foo a, IInterface b)
    {
        return a.Add<Foo>(b);
    }
}

class Bar : IInterface
{
    public int X { get; set; }
    public int Y { get; set; }

    public static IInterface operator +(Bar a, IInterface b)
    {
        return a.Add<Bar>(b);
    }
}

class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo { X = 5, Y = 3 };
        var bar = new Bar { X = 3, Y = 5 };

        var result = foo + bar;
        Console.WriteLine(result.GetType().Name + " " + result.X + " " + result.Y);
        result = bar + foo;
        Console.WriteLine(result.GetType().Name + " " + result.X + " " + result.Y);

        Console.ReadLine();
    }
}

Если бы ваши интерфейсы содержали больше, чем просто контракты, это было бы нарушением проектирования по контракту.

7
ответ дан 29 November 2019 в 22:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: