代码之家  ›  专栏  ›  技术社区  ›  ChaosPandion

定义这个通用接口以便编译的最干净的方法是什么?

  •  2
  • ChaosPandion  · 技术社区  · 15 年前

    因为,两个参数相同但返回值不同的方法将无法编译。在不失去清晰度的情况下,定义这个接口的最佳方法是什么?

    public interface IDuplexChannel<T, U>
    {
        void Send(T value, int timeout = -1);
        void Send(U value, int timeout = -1);
        bool TrySend(T value, int timeout = -1);
        bool TrySend(U value, int timeout = -1);
        T Receive(int timeout = -1);
        U Receive(int timeout = -1);
        bool TryReceive(out T value, int timeout = -1);
        bool TryReceive(out U value, int timeout = -1);
    }
    

    public interface IDuplexChannel<T, U>
    {
        void Send(T value, int timeout = -1);
        void Send(U value, int timeout = -1);
        bool TrySend(T value, int timeout = -1);
        bool TrySend(U value, int timeout = -1);
        void Receive(out T value, int timeout = -1);
        void Receive(out U value, int timeout = -1);
        bool TryReceive(out T value, int timeout = -1);
        bool TryReceive(out U value, int timeout = -1);
    }
    

    通用版本,有点笨拙,但它的工作。

    public interface IDuplexChannel<T, U>
    {
        void Send(T value, int timeout = -1);
        void Send(U value, int timeout = -1);
        bool TrySend(T value, int timeout = -1);
        bool TrySend(U value, int timeout = -1);
        V Receive<V>(int timeout = -1) where V : T, U;
        bool TryReceive(out T value, int timeout = -1);
        bool TryReceive(out U value, int timeout = -1);
    }
    
    3 回复  |  直到 15 年前
        1
  •  5
  •   Community Mohan Dere    5 年前

    public interface IDuplexChannel<TSend, TReceive>
    {
        void Send(TSend data);
        TReceive Receive();
    }
    

    也就是说,你应该使用WCF, 尤其地 因为您使用的是.NET 4.0。

            "PERSON" A                                     "PERSON" B
                O            int ----------------->            O
               -|-           <-------------- string           -|-
               / \                                            / \
    IDuplexChannel<int, string>                     IDuplexChannel<string, int>
    
        2
  •  4
  •   Daniel A. White    15 年前

    重命名这两个方法。它们只在返回类型上有所不同。

    T Receive(int timeout = -1);
    U Receive(int timeout = -1);
    

    注意,我没有测试过这个。试试这个。

    R Receive<R>(int timeout = -1);
    
        3
  •  3
  •   Tomas Petricek    15 年前

    问题确实是有两个 Receive 只因返回类型不同而不同的方法。因为您的类型表示一个双工通道,所以您必须复制接口中的所有内容—我相信一个更简单的方法是定义一个允许您表示的类型 “T或U” 价值观。这与 Tuple<T, U> “T和U”

    // Represents either a value of type T or a value of type U
    class Either<T, U> { 
      public bool TryGetFirst(out T val);
      public bool TryGetSecond(out U val);
    }
    
    // For constructing values of type Either<T, U>
    static class Either {
      public static Either<T, U> First<T, U>(T val);
      public static Either<T, U> Second<T, U>(U val);
    }
    

    此类的示例用法可能如下所示:

    var val = Either.First<int, string>(42);
    
    int num;
    string str;
    if (val.TryGetFirst(out num)) 
      Console.WriteLine("Got number: {0}", num);
    else if (val.TryGetSecond(out str)) 
      Console.WriteLine("Got string: {0}", str);
    

    然后,您可以使用更简单的接口来表示双工通道:

    public interface IDuplexChannel<T, U> { 
        void Send(Either<T, U> value, int timeout = -1); 
        bool TrySend(Either<T, U> value, int timeout = -1); 
        Either<T, U> Receive(int timeout = -1); 
        bool TryReceive(out Either<T, U> value, int timeout = -1); 
    } 
    

    正如乔希所建议的,我也会摆脱 接收 Send 方法。为什么?因为它使实现接口变得简单,并且您可以轻松地提供 接收 发送 依据 TryReceive TrySend 作为一种扩展方法。因此,您将得到一个接口:

    public interface IDuplexChannel<T, U> { 
        bool TrySend(Either<T, U> value, int timeout = -1); 
        bool TryReceive(out Either<T, U> value, int timeout = -1); 
    } 
    

    public static Either<T, U> Receive
        (this IDuplexChannel<T, U> ch, int timeout = -1) {
      Either<T, U> v;
      if (!ch.TryReceive(out v, timeout)) throw new Exception(...);
      return v;
    }
    
    推荐文章