C # неявный / явный приведение в общий тип для типа generic class [duplicate]

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

2 ответа

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

Вы все еще можете наследовать от абстрактного базового класса, который реализует интерфейс и предоставляет логику, необходимую для бросков или перегрузки оператора. Это не нарушает ориентированный на интерфейс дизайн. Классы, которые не наследуются от общего базового класса, но реализуют интерфейс, по-прежнему должны самостоятельно реализовать свои собственные неявные броски и перегрузки операторов. Если вы хотите централизовать логику работы с классами, которые обычно реализуют интерфейс, вы можете сделать это в 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
ответ дан cfeduke 22 August 2018 в 13:14
поделиться

Один из способов сделать это, если есть листинг / преобразование, которое, вероятно, вам нужно будет определить, как метод на вашей inteface, например

public interface ISomeInterface
{
   TargetType ToTargetType();
}

Затем в абстрактной базе класс, вы можете определить импликт / явное приведение и иметь реализацию ToTargetType(), просто вызвать оператор трансляции, например

public abstract class SomeAbstractClass : ISomeInterface
{
  public TargetType ToTargetType()
  {
    return (TargetType)this;
  }

  public static explicit operator TargetType(SomeAbstractClass obj)
  {
    //Actual cast logic goes here
  }
}

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

3
ответ дан RobV 22 August 2018 в 13:14
поделиться
Другие вопросы по тегам:

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