如何根据条件将变量赋值为两种不同类型中的一种
本文关键字:同类型 一种 两种 条件 何根 变量 赋值 | 更新日期: 2023-09-27 17:50:32
我有两个字典,一个用于我作为主机的文件传输,另一个用于我作为客户端的文件传输。
我为我的程序的一个区域所做的代码是完全相似的,除了引用这些项中的一个或另一个。因此,我尽量避免重复代码。
public void UpdateFileTransferItems(FileTransferItem.FileTransferRole role)
{
// If the role is Sender then the variable is fileTransferSessionsAsHost, otherwise it is fileTransferSessionsAsClient.
var fileTransferSessions = role == FileTransferItem.FileTransferRole.Sender ? fileTransferSessionsAsHost : fileTransferSessionsAsClient;
foreach (var hostSession in fileTransferSessions)
{
Do Work in here.
}
}
显然三元操作符不工作,但我怎么能创建代码,将做什么,我想做的?如果角色是发送者,我希望变量是对fileTransferSessionsAsHost
的引用,否则我希望它是fileTransferSessionsAsClient
。
我是在用一种迟钝的方式来谈论这个吗?我应该只是复制代码,并有两个if语句吗?
编辑:如果我想不出更好的办法,这就是我现在必须做的。如果仔细查看,除了名称和引用的字典项之外,每个代码都是相同的。
public void UpdateFileTransferItems(FileTransferItem.FileTransferRole role)
{
if (role == FileTransferItem.FileTransferRole.Sender)
{
foreach (var hostSession in fileTransferSessionsAsHost)
{
var fileTransferItem = activeFileTransfers.FirstOrDefault(fti => fti.SessionId == hostSession.Key.SessionId);
if (fileTransferItem == null)
{
activeFileTransfers.Add(new FileTransferItem(hostSession.Key.FileName,
hostSession.Key.FileExtension,
hostSession.Key.FileLength,
FileTransferItem.FileTransferRole.Sender,
hostSession.Key.SessionId));
}
else
{
fileTransferItem.Update(hostSession.Value.TotalBytesSent,
hostSession.Value.TransferSpeed,
hostSession.Value.TotalBytesSent == hostSession.Key.FileLength);
}
}
}
else
{
foreach (var clientSession in fileTransferSessionsAsClient)
{
var fileTransferItem = activeFileTransfers.FirstOrDefault(fti => fti.SessionId == clientSession.Key.SessionId);
if (fileTransferItem == null)
{
activeFileTransfers.Add(new FileTransferItem(clientSession.Key.FileName,
clientSession.Key.FileExtension,
clientSession.Key.FileLength,
FileTransferItem.FileTransferRole.Sender,
clientSession.Key.SessionId));
}
else
{
fileTransferItem.Update(clientSession.Value.TotalBytesSent,
clientSession.Value.TransferSpeed,
clientSession.Value.TotalBytesSent == clientSession.Key.FileLength);
}
}
}
}
为了达到您的目的,两个类需要从相同的基类或接口派生。例如,如果你有一个叫做IFileTransferSessions
的通用接口,那么下面的代码应该可以工作:
IFileTransferSessions fileTransferSessions = role == FileTransferItem.FileTransferRole.Sender ? fileTransferSessionsAsHost : fileTransferSessionsAsClient;
或者如果您真的想保留var
语法:
var fileTransferSessions = role == FileTransferItem.FileTransferRole.Sender ? fileTransferSessionsAsHost as IFileTransferSessions : fileTransferSessionsAsClient;
注意,您只需要将第一个三级结果强制转换到接口,或者您可以同时执行这两个操作。
var
关键字不像VB中的Variant
,它在编译时不关心类型是什么。(这更接近c#中的dynamic
)它所做的就是从下面的用法中派生类型。对于要派生的两个不同的类,它们必须共享一个公共基类或接口,即使这样,var
也需要知道该基类定义才能正常工作。
有几种不同的方法可以解决这个问题。使用接口是最安全、最合理的方法(或者使用基类)。它们实现了相同的属性,所以它们都可以有一个接口来公开这些属性,然后你可以将它们强制转换到接口。
如果你不能(或不愿意)修改类定义来使用接口,那么你也可以使用反射或动态。它们都容易受到运行时错误的影响,这比使用接口得到的编译时错误更糟糕。与反射相比,使用动态具有更清晰的语法,也更容易编写。只需将这两个项强制转换为dynamic,并将它们存储在动态引用中。然后你可以调用它们的必要属性。
dynamic fileTransferSessions = role == FileTransferItem.FileTransferRole.Sender ?
(dynamic)fileTransferSessionsAsHost :
(dynamic)fileTransferSessionsAsClient;
动态键入信息:http://msdn.microsoft.com/en-us/library/dd264736.aspx
考虑下面的代码。
Dictionary<int, string> d1 = new Dictionary<int, string>();
Dictionary<int, string> d2 = new Dictionary<int, string>();
bool flag = true;
var d = flag ? d1 : d2;
它可以工作,因为d1
和d2
的类型匹配(或者从一个转换到另一个)。这是关键。如果三元操作符返回值的类型不同,则不能推断操作符的返回类型,这就是问题所在。
实际上,您可以显式地将一个或两个操作数强制转换为一个公共接口(如果有的话)以使其工作
如果您至少可以从同一个基类或接口派生hostSession和clientSession,那么您可以通过分解其中的一些来大大减少代码:
public void UpdateFileTransferItems(FileTransferItem.FileTransferRole role)
{
if (role == FileTransferItem.FileTransferRole.Sender)
{
foreach (var hostSession in fileTransferSessionsAsHost)
{
UpdateTransfers(hostSession);
}
}
else
{
foreach (var clientSession in fileTransferSessionsAsClient)
{
UpdateTransfers(clientSession);
}
}
}
private void UpdateTransfers(SessionBaseType session)
{
var fileTransferItem = activeFileTransfers.FirstOrDefault(fti => fti.SessionId == session.Key.SessionId);
if (fileTransferItem == null)
{
activeFileTransfers.Add(new FileTransferItem(session.Key.FileName,
session.Key.FileExtension,
session.Key.FileLength,
FileTransferItem.FileTransferRole.Sender,
session.Key.SessionId));
}
else
{
fileTransferItem.Update(session.Value.TotalBytesSent,
session.Value.TransferSpeed,
session.Value.TotalBytesSent == session.Key.FileLength);
}
}
如果您不能修改会话类以使其具有共同的祖先,那么另一种方法是制作一个暴露必要属性的包装器类,并且您基本上仍然可以使用上述代码,只是您将拥有UpdateTransfers(new SessionWrapper(clientSession));
而不是UpdateTransfers(clientSession);
。