因为,两个具有相同参数但返回值不同的方法将无法编译。在不失去清晰度的情况下定义此界面的最佳方法是什么?
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);
}
我考虑过使用params,但这样会使用起来有点尴尬。
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);
}
答案 0 :(得分:5)
主要问题是您正在尝试同时从两端查看双工通道。数据在双工通道上双向传播,但仍有明确的终点。你在一端发送的是你收到的另一端。
public interface IDuplexChannel<TSend, TReceive>
{
void Send(TSend data);
TReceive Receive();
}
"PERSON" A "PERSON" B
O int -----------------> O
-|- <-------------- string -|-
/ \ / \
IDuplexChannel<int, string> IDuplexChannel<string, int>
答案 1 :(得分:4)
重命名这两种方法。它们仅因返回类型而不同。
T Receive(int timeout = -1);
U Receive(int timeout = -1);
注意,我没有测试过这个。试试这个。
R Receive<R>(int timeout = -1);
答案 2 :(得分:3)
问题确实存在两种Receive
方法,它们仅因返回类型而不同。因为您的类型代表双工通道,您必须复制界面中的所有内容 - 我认为更简单的方法是定义一种类型,允许您表示“T或U”值。这与Tuple<T, U>
非常相关,现在在.NET中,它允许您表示“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);
}
正如Josh所说,我也会摆脱Receive
和Send
方法。为什么?因为它使界面的实现变得简单,您可以使用Receive
和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;
}