使用NotSupportedException时是不是很糟糕?

时间:2013-08-05 00:49:35

标签: c# design-patterns interface

我正在构建本地化目录并且存在设计困境。目前,目录存储Dictionary<string, IString>来存储翻译,其中IString可以有两种类型:SingularPlural。这是IString的简化版本:

public interface IString
{
    void SetSingular(string singular);

    string GetSingular(params object[] args);

    void SetPlural(PluralCategory category, string plural);

    string GetPlural(PluralCategory category, params object[] args);
}

然后,当我实现Singular时,我会为目录捕获的复数方法抛出NotSupportedExceptionPlural对单数方法执行相同的操作。

public class Singular : IString
{
    // ...

    public string GetPlural(PluralCategory category, params object[] args)
    {
        throw new NotSupportedException(string.Format(
            "Singular strings don't support GetPlural({0}, {1})",
            category, args));
    }

    public void SetPlural(PluralCategory category, string plural)
    {
        throw new NotSupportedException(string.Format(
            "Singular strings don't support SetPlural({0}, {1})",
            category, plural));
    }
}

这种设计来自于对单数和复数键必须唯一的要求,但我觉得实现非相关方法并抛出NotSupportedException并不能很好地发挥作用。

第二种设计是存储Dictionary<string, StringType>进行密钥检查,其中StringType是枚举,然后使用两个额外的词典Dictionary<string, Singular>Dictionary<string, Plural>来使用取决于StringType的值。这使它更复杂,但不会破坏界面概念。

那么,您怎么看?我的第一个想法是NotSupportedException使用不当吗?我应该选择第二种设计还是其他设计?

编辑:基于@dasblinkenlight理念,更清晰的解决方案是统一界面方法,将SingularPlural合并为一个。{1}}或PluralCategory.None。单数只有public interface IString { string GetString(PluralCategory category, params object[] args); bool HasCategory(PluralCategory category); } public class Singular : IString { private string Text; public string GetString(PluralCategory category, params object[] args) { if (category == PluralCategory.None) { if (Text == null || args == null || args.Length == 0) { return Text; } return string.Format(Text, args); } return null; } public bool HasCategory(PluralCategory category) { return category == PluralCategory.None; } } public class Plural : IString { private Dictionary<PluralCategory, string> Texts = new Dictionary<PluralCategory, string>(); public string GetString(PluralCategory category, params object[] args) { string text; if (Texts.TryGetValue(category, out text)) { if (text == null || args == null || args.Length == 0) { return text; } return string.Format(text, args); } return null; } public bool HasCategory(PluralCategory category) { return Texts.ContainsKey(category); } } ,而Plurals永远不允许包含此类别。这受限于setter方法,由特定实现定义的接口之外(setter方法不在下面显示)。

{{1}}

1 个答案:

答案 0 :(得分:7)

你是对的,把NotSupportedException扔在这种情况下不是一个好主意。通常,您实现的接口是提供一组通用的操作,以便统一&#34;一组不同的类,为一组常见操作提供不同的实现。

但是,在您的情况下,不相似的类无法统一&#34;它们不仅保留了自己的实现,还保留了自己的接口。当您尝试统一使用它们时,代码会抛出异常。与将object保持为IString相比,通用界面并没有给你那么多 - 用户在拨打电话之前必须知道NotSupportedException后面是什么类,否则他们可能会看到string

有几种解决这个问题的方法:一种方法是统一单数和复数方法,返回比简单public enum SingularOrPluralCategory { Singular, // The rest of the PluralCategory enum values } public class StringForm { public string Text {get; private set;} public SingularOrPluralCategory Category {get; private set;} } public interface IString { // You may want to omit the setter from the interface, adding it to the class instead void SetForm(SingularOrPluralCategory category, string plural); StringForm GetForm(SingularOrPluralCategory category, params object[] args); } 更复杂的答案:

StringForm

现在,单个实现将返回Singular CategoryStringForm的{​​{1}},而复数实现将返回IString多个类别中的一个。试图在IString的单个子类上设置复数类别可能仍然是一个错误,但是您可以通过将setter移动到类上来解决这个问题,从而无法在单个子类上调用具有类别的setter。 {{1}}。