.Net时区验证的正确方法

Rom*_*kin 2 .net c# timezone

我有一个方法可以接受.Net(或Windows)时区ID作为字符串:

public void SaveTimezoneId(string timezoneId) { ... }
Run Code Online (Sandbox Code Playgroud)

如您所知,.Net中的时区是这样的字符串:

  • 阿拉伯标准时间
  • 俄罗斯标准时间
  • 加拿大中部标准时间

等等

在将它们保存到数据库之前,我需要一种验证它们的方法。我现在所做的如下:

    try
    {
        TimeZoneInfo.FindSystemTimeZoneById(timezoneId);

        CurrentUser.TimezoneId = timezoneId;
        context.SaveChanges();

        return JsonSuccess();
    }
    catch(Exception)
    {
        return JsonError("Invalid time zone");
    }
Run Code Online (Sandbox Code Playgroud)

但这完全违反了良好软件开发的主要原则之一:永远不要依赖异常。而且,异常的代价很高。

还有其他方法可以执行此检查并摆脱try-catch吗?

谢谢。

ang*_*son 5

首先,如果您没有替代方案,或者替代方案(也)成本高昂,那么可以采用例外方式。我并不是要您停止寻找替代方案,但不要禁止例外,它们与所有类型的代码一样都有自己的位置。

但是,您有另一种选择,可以调用TimeZoneInfo.GetSystemTimeZones并自己进行查找:

void Main()
{
    var timeZones = TimeZoneInfo
        .GetSystemTimeZones()
        .ToDictionary(stz => stz.Id);

    TimeZoneInfo tz;
    if (timeZones.TryGetValue("UTC-11", out tz))
        tz.Dump();
    else
        Debug.WriteLine("No such timezone");
}
Run Code Online (Sandbox Code Playgroud)

如果您只需要知道ID是否有效:

void Main()
{
    var timeZoneIds = new HashSet<string>(TimeZoneInfo
        .GetSystemTimeZones()
        .Select(tzi => tzi.Id));

    timeZoneIds.Contains("UTC-11").Dump();
}
Run Code Online (Sandbox Code Playgroud)

这两个都可以在LINQPad中进行测试。

如果您需要进行多次查找/检查并且可以节省一些内存以提高速度,则可以将字典/哈希集存储在两次调用之间的安全位置。