Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 定义这个通用接口以便编译的最干净的方法是什么?_C#_.net_Generics_C# 4.0 - Fatal编程技术网

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

C# 定义这个通用接口以便编译的最干净的方法是什么?,c#,.net,generics,c#-4.0,C#,.net,Generics,C# 4.0,因为,具有相同参数但不同返回值的两个方法将无法编译。在不失去清晰度的情况下,定义此接口的最佳方法是什么 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 valu

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

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);
}
公共接口IDuplexChannel
{
无效发送(T值,int超时=-1);
无效发送(U值,int超时=-1);
bool TrySend(T值,int timeout=-1);
bool TrySend(U值,int timeout=-1);
T接收(int超时=-1);
U接收(int超时=-1);
bool TryReceive(out T值,int timeout=-1);
bool TryReceive(out U值,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);
}
公共接口IDuplexChannel
{
无效发送(T值,int超时=-1);
无效发送(U值,int超时=-1);
bool TrySend(T值,int timeout=-1);
bool TrySend(U值,int timeout=-1);
无效接收(out T值,int timeout=-1);
无效接收(out U值,int超时=-1);
bool TryReceive(out T值,int timeout=-1);
bool TryReceive(out U值,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);
}
公共接口IDuplexChannel
{
无效发送(T值,int超时=-1);
无效发送(U值,int超时=-1);
bool TrySend(T值,int timeout=-1);
bool TrySend(U值,int timeout=-1);
V接收(int timeout=-1),其中V:T,U;
bool TryReceive(out T值,int timeout=-1);
bool TryReceive(out U值,int timeout=-1);
}

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

T Receive(int timeout = -1);
U Receive(int timeout = -1);
注意,我没有测试过这个。试试这个

R Receive<R>(int timeout = -1);
R接收(int超时=-1);

问题确实在于,有两种
Receive
方法仅在返回类型上有所不同。因为您的类型表示一个双工通道,所以您必须复制接口中的所有内容-我认为一个更简单的方法是定义一个允许您表示“T或U”值的类型。这与Tuple非常相关,Tuple现在位于.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 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;
}
扩展方法大致如下所示:

// 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 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;
}
public static或Receive
(此IDuplexChannel ch,int timeout=-1){
要么v;
如果(!ch.TryReceive(out v,timeout))抛出新异常(…);
返回v;
}

主要问题是您试图同时从两端查看双工信道。数据在双工信道上双向传输,但仍有确定的端点。你在一端发送的是你在另一端收到的

public interface IDuplexChannel<TSend, TReceive>
{
    void Send(TSend data);
    TReceive Receive();
}
公共接口IDuplexChannel
{
无效发送(发送数据);
TReceive Receive();
}
这就是说,您无论如何都应该使用WCF,特别是因为您使用的是.NET4.0。 编辑:图片
“人”A“人”B
O int------------------->O


-|-它在哪里编译?错误是什么?如果有人使用过构造,你会很开心的。@Eric-回来指出我的愚蠢吧?在我的代码实验项目中有一个很好的理由,我不想指出任何人的愚蠢。我只是想指出这个界面设计可能存在的一个潜在问题。CLR在任何类型上都存在许多问题,这些问题可能会导致泛型构造下的签名统一;在C#泛型的原始设计中,甚至声明您描述的类型都是非法的。对于这种签名统一导致的特别恶劣的情况,请参阅您的第二个建议,这是我的退路。我不喜欢它的原因是您必须明确定义类型
Receive
。。。我要说的是,去掉Receive方法,只使用TryReceive。无论什么时候,只要让我选择某物或尝试某物的方法,我总是喜欢后者。@Josh-我考虑过这样做,但是我决定添加非尝试方法,这样如果你无法处理失败,你就不必自己提出异常。我会说保留尝试和非尝试版本。如果遵循标准的.NET模式,则这两种模式具有不同的调用语义。我也会避免同时使用Receive和TryReceive use out参数……这会违背同时使用这两个参数的目的和价值。为什么您会说TryReceive会更常用?除非我需要显式地处理接收失败的情况,否则我通常使用接收并让异常冒泡。您可以对这两种情况进行辩论,这就是为什么大多数Microsoft界面中都存在这两种情况。归根结底,这是一个与上下文相关的决定,您使用哪一个,两者都有价值。@chaospandio:Tomas关于在接口中只使用一个版本的Send和Receive的简单性是正确的。这个答案也值得回顾。但实际实施这是一个非常糟糕的想法。您将使用泛型来指示您可以在通道上发送什么,然后使用大量的变通方法来防止编译器强制执行它。。。重点是什么?我假设最初的inteface声明是问题作者实际需要的。如果以不同的方式设计类型更好(只支持接收一种类型的值和发送另一种类型的值),那么这当然太复杂了。@280Z28-如果我保留我的原始设计,我会使用它。特别是因为我只是在试验线程间通信?然而,我确实明白你关于接口名称语义的观点。尽管它没有回答我最初的问题,但它确实通过指出我设计中的缺陷来解决问题。Eric Lippert获得部分学分。@ChaosPandion:NetNamedPipeBinding可用于