C#泛型类型typedef / alias和InvalidCastException

时间:2015-10-22 10:52:38

标签: c# generics types alias

使用泛型类型的泛型类型变得难以读取,所以我想创建一个更短的别名。例如:

1)在这种情况下,通过子类化。

public class Parameters : Dictionary<string, string> {};

对我而言,这实际上只是一个别名,所以在某些时候我想做:

var myDictionary = new Dictionary<string, string>;
// some operations on myDictionary
Parameters parameters = (Parameters)myDictionary;

我得到一个InvalidCastOperation,我假设因为我想从基类转换为继承类(我的“技巧”来获取别名)。

不幸的是,这也不允许挽救这一天:

public class Parameters : Dictionary<string, string>
{
    public static implicit operator Parameters(Dictionary<string, string> dict)
    {
        Parameters res = new Parameters();
        foreach (var parameter in dict)
            res.Add(parameter.Key, parameter.Value);
        return res;
    }
};

无法编译。所以这看起来像死路一条。

我或许可以编写我自己必须明确调用的方法,但隐式转换会更好。

2)或者,我可以在文件级别上进行delcare:

using Parameters = System.Collections.Generic.Dictionary<string, string>;

这样做的缺点是,我需要为每个要使用其类型的文件声明它(或使用完整语法)。

如何获得具有隐式转换的别名,并且只需要声明一次?

修改/添加
为了更好地理解,这是实际的代码。

public delegate Parameters UrlHandler(Parameters jsonParameters);
public class RequestHandlers : Dictionary<string, UrlHandler> { };
public class Parameters : Dictionary<string, string> { };

当我在2个参数之间进行Linq-union时会出现问题,这会导致字典。

2 个答案:

答案 0 :(得分:3)

在正常情况下,我不认为别名是一种好习惯。我相信它会降低代码的可读性。但是,如果您认为在特定情况下它会使代码更具可读性,如果您认为Parameters可能不仅仅是字典,那么您可以继承{ {1}}并使用其复制构造函数:

Dictionary<string,string>

这将允许您这样做:

public class Parameters : Dictionary<string, string>
{
    public Parameters(IDictionary<string, string> dict) : base(dict)
    {
    }
};

以及:

var myDictionary = new Dictionary<string, string>();

Parameters parameters = new Parameters(myDictionary);

答案 1 :(得分:2)

你过分依赖老派C.在C中,别名就是那个 - 这个名字的快捷方式。当然,也许这可以为你节省一大堆按键,但现在这几乎不值得,尤其是像IntelliSense这样的功能。

您不必仅为同一类型指定不同的名称,而是希望创建自己的类型,只显示您的用例所需的任何内容。隐藏和抽象,而不仅仅是别名。

例如,您已获得Parameters。你真的想要Dictionary<string, string>的所有属性和方法吗?你真的想要允许来回隐式转换吗?

有很多解决方案更适合现代编程。但是你需要考虑你真正想要的东西 - 它代表Parameters的类型意味着什么?也许你想从某个地方传递一组参数,在某一点创建(例如从配置中创建)并且只在其他地方读取?只需创建自己的类型,并公开您真正想要的界面:

public class Parameters
{
  private readonly IDictionary<string, string> _parameters;

  public Parameters(IDictionary<string, string> parameters)
  {
    _parameters = parameters;
  }

  public string this[string key]
  {
    get { return _parameters[key]; }
  }
}

现在你只是暴露了真正重要的界面。你需要一种迭代参数的方法吗?只需实施IEnumerable<KeyValuePair<string, string>>

真的需要字典吗?然后忘记使用相当具体的Dictionary<string, string>类,并使用接口IDictionary<string, string>代替 - 这是Parameters类可以轻松实现的东西(可能只是委托给基础字典,根据您的要求)。现在,您可以从字典中创建新的Parameters ... Parameters本身仍然是字典,并且可以在其他IDictionary<string, string>可以使用的地方使用,不需要将它改写为Dictionary<string, string> - 为什么你还想这样做呢?

考虑您的投射操作员尝试中的错误消息 - &#34;不允许用户定义到基类的转换和#34;。您是否考虑过如果没有导致错误会发生什么?你打破了所有继承和接口的工作方式 - 所以你的类型是Dictionary<string, string>,但不是真的吗?如果你对Dictionary<string, string>执行隐式转换,它会复制一个副本,但是如果你进行了显式转换,它仍然是同一个实例?子类型总是可以转换为父类型 - 这就是基于类的OOP的整点...

拥抱OOP。或FP,C#也支持得足够好。但坚持C#中的C风格编程是行不通的,你只会给每个人带来很多痛苦:)