将short强制转换为枚举类型,再转换为字符串的目的是什么?

3

我正在查看并尝试理解DnDns项目,这是一个非常令人印象深刻的项目,但我遇到了一个方法,我不明白背后的原因。

public static string GetServByPort(short port, ProtocolType proto)
{
    StringBuilder ans = new StringBuilder();

    switch (proto)
    {
        case ProtocolType.Tcp: 
        {
            TcpServices tcps;
            tcps = (TcpServices)port;
            ans.Append(tcps);
            ans.Append("(");
            ans.Append(port);
            ans.Append(")");
            break;
        }
        case ProtocolType.Udp:
        {
            UdpServices udps;
            udps = (UdpServices)port;
            ans.Append(udps);
            ans.Append("(");
            ans.Append(port);
            ans.Append(")");
            break;
        }
        default:
        {
            ans.Append("(");
            ans.Append(port);
            ans.Append(")");
            break;
        }
    }
    return ans.ToString();
}

TcpServices 和 UdpServices 是枚举。这是 TcpServices 的内容:
public enum TcpServices : short
{
    /// <summary>
    /// Domain Name Server Port
    /// </summary>
    Domain = 53
}

这里是 UdpServices:

public enum UdpServices : short
{
    /// <summary>
    /// Domain Name Server Protocol Port
    /// </summary>
    Domain = 53
}

假设端口号为1. 如果协议类型是TCP或UDP,则输出如下:

1(1)

如果协议类型是其他任何东西,则输出如下:

(1)

因此,我希望为我的项目重写此方法(仍然全面致谢原始开发人员等):

private static string GetServerByPort(short port, ProtocolType protocolType)
{
    if (protocolType == ProtocolType.Tcp || protocolType == ProtocolType.Udp)
    {
        return string.Format("{0}({0})", port);
    }

    return string.Format("({0})", port);
}

我写了下面这个简短的控制台应用程序来进行测试:
using System;
using System.Net.Sockets;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(GetServByPort(1, ProtocolType.Tcp));
            Console.WriteLine(GetServByPort(2, ProtocolType.Udp));
            Console.WriteLine(GetServByPort(3, ProtocolType.SpxII));

            Console.ReadLine();
        }

        public static string GetServByPort(short port, ProtocolType proto)
        {
            switch (proto)
            {
                case ProtocolType.Tcp:
                    return string.Format("{0} ({1})", (TcpServices)port, port);
                case ProtocolType.Udp:
                    return string.Format("{0} ({1})", (UdpServices)port, port);
                default:
                    return string.Format("({0})", port);
            }
        }
    }

    public enum UdpServices : short
    {
        Domain = 53
    }

    public enum TcpServices : short
    {
        Domain = 53
    }
}

以下是我的输出结果:

截图

然而我不禁想到开发者们为什么要这样复杂地设计,我可能没有看到其中的原因。

我的问题是,我计划重构这个方法的方式是否正确,还是原始开发人员所做的方式有其合理性,如果我以更简单的方式进行操作,那么在后续过程中是否会出现问题?

3个回答

6
当在枚举类型上调用ToString()方法时,如果存在枚举值的名称,将使用该名称。(当没有相应的命名值时,它将给出数字版本。)因此,例如,在您的TcpServices案例中,如果值为53,则结果将为Domain(53)在原始代码中-但在您建议替换的代码中为53(53)
然而,在这里使用StringBuilder是没有意义的。我会将原始方法重写为:
public static string GetServByPort(short port, ProtocolType proto)
{
    switch (proto)
    {
        case ProtocolType.Tcp: 
            return string.Format("{0} ({1})", (TcpServices) port, port);
        case ProtocolType.Udp:
            return string.Format("{0} ({1})", (UdpServices) port, port);
        default:
            return string.Format("({0})", port);
    }
}

感谢您的回答,我一开始也是这么想的。但为了确认,我写了一个快速测试应用程序,结果并不符合我的预期,所以才会造成困惑。我已经更新了我的问题。 - JMK
@JMK "在枚举上调用ToString()将使用枚举值的名称,如果有的话。" 您调用它时使用的值不对应于任何命名的枚举值。 - Daniel Fischer

3
对于知名的服务,您的输出将如下所示:
Domain (53)
HTTP (80)
HTTPS (445)
FTP (21)

等等。而未知的将会像你展示的一样:

1 (1)
2 (2)

etc.


我也是这样认为的,但我已经更新了问题并解释了我看到了什么,以及我为什么感到困惑。我是不是做错了什么傻事? - JMK
将您的更新代码更改/附加到端口53,您应该会看到一个差异。 - Jesse C. Slicer

2
如果值实际上是枚举成员之一,该函数将返回类似于"Domain(53)"而不是"53(53)"的内容。StringBuilder本质上为所有内容调用ToString,对于枚举值,如果存在名称,则返回该名称(否则为数字)。
如果您想重构一些代码,可以将常见的"(port)"部分移动到switch外部,完全删除默认情况,并且摆脱不需要的临时变量。例如:
public static string GetServByPort(short port, ProtocolType proto)
{
    StringBuilder ans = new StringBuilder();

    switch (proto)
    {
        case ProtocolType.Tcp: 
            ans.Append((TcpServices)port);
            break;
        case ProtocolType.Udp:
            ans.Append((UdpServices)port);
            break;
    }

    ans.Append("(").Append(port).Append(")");

    return ans.ToString();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接