我有一个派生自TcpClient的类,例如
class ZClient : TcpClient
{
public byte[] Buffer { get; set; }
public Queue<byte[]> Queue {get; set;}
}
创建TcpClient的方法
...
TcpListener listener = ar.AsyncState as TcpListener;
ZClient client = listener.EndAcceptTcpClient(ar) as ZClient;
当我将通常返回TcpClient的listener.EndAcceptTcpClient(ar)转换为ZClient时,对象'client'为null。我试图做的是非法的吗?
更新:是否可以将ZClient基类的属性设置为等于通过构造函数传入的TcpClient,以避免必须有一个额外的属性来引用TcpClient的? e.g。
public ZClient(TcpClient client)
{
base = client; // I'm aware this doesn't work.
}
答案 0 :(得分:6)
因为它倒退了。 TcpClient不包含Buffer或Queue,因为它不是ZClient。苹果是水果,但不是所有水果都是苹果。
您需要某种显式转换。您可以提供一个接受TcpClient的ZClient构造函数,或者在TcpClient上提供返回ZClient的扩展方法。这些中的任何一个都可能需要使ZClient成为TcpClient的包装类,而不是ZClient的子类。
答案 1 :(得分:4)
所有ZClient
都是TcpCplient
,但并非所有TcpClient
都是ZClient
s * 。 TcpClient
返回的TcpListener.EndAcceptTcpClient
是TcpClient
,不能用作ZClient
。您可以包装生成的TcpClient
。我建议使用
private readonly TcpClient;
public ZClient(TcpClient tcpClient) {
this.tcpClient = tcpClient;
}
* :也许一个不同的例子会有所帮助
class Animal { }
class Cat {
public int NumberOfLives { get; private set; }
public Cat() { NumberOfLives = 9; }
}
您是否能够(使用as
)转换由Animal
返回Cat
的方法返回的任何对象?并非所有Animal
都有脚,就像并非所有TcpClient
都有一个名为byte[]
的{{1}}或一个名为Buffer
的{{1}}。因此,您无法将通用Queue<byte[]>
视为Queue
,就像您无法将通用TcpClient
视为ZClient
一样。
答案 2 :(得分:1)
你可能想要一个“有一个”而不是“是一个”TcpClient和ZClient之间的关系
class ZClient
{
public ZClient(TcpClient client)
{
this.client = client;
}
public TcpClient client {get; set;}
public byte[] Buffer { get; set; }
public Queue<byte[]> Queue {get; set;}
}
然后您可以将调用委托给底层TcpClient
答案 3 :(得分:0)
我试图做的是非法的吗?
是。 TcpListener
怎么能知道如何提出ZClient
?如果有,那么Buffer
和Queue
属性会做什么?
答案 4 :(得分:0)
listener.EndAcceptTcpClient(ar)
正在给你TcpClient
。您无法取TcpClient
并假装它是ZClient
。这不是继承的工作方式。
简而言之:
ZClient
都是TcpClient
。TcpClient
都是ZClient
s。例如,马是动物。并非所有动物都是马。
答案 5 :(得分:0)
如果从侦听器获取TcpClient,则侦听器将像往常一样返回TcpClient。你永远不会新兴ZClient。 TcpListener对您的新类一无所知,因此无法创建它。如果您只想拥有一个为TcpClient添加功能的对象,您可能只想使用组合而不是继承。简单地有一个ZClient,它通过在内部存储一个TcpClient来包装它,并添加你想要的任何功能。