c# – 为复杂泛型类型创建类或接口
作者:互联网
我正在尝试为一种对象列表列表创建别名.具体来说,我想缩短我必须为这种类型做的所有输入:
IReadOnlyList<IReadOnlyList<MyObject>>
我的尝试在这里得到证明:
using System.Collections.Generic;
namespace MyApp
{
class Program
{
public class MyObject
{
public static IMyCollection GetCollection()
{
var a = new List<MyObject>();
a.Add(new MyObject());
var b = new List<IReadOnlyList<MyObject>>();
b.Add(a.AsReadOnly());
return b.AsReadOnly();
}
}
public interface IMyCollection : IReadOnlyList<IReadOnlyList<MyObject>>
{
}
static void Main(string[] args)
{
var collection = MyObject.GetCollection();
}
}
}
不幸的是,这不会编译.有错误是:
Cannot implicitly convert type
'System.Collections.ObjectModel.ReadOnlyCollection<System.Collections.Generic.IReadOnlyList<MyApp.Program.MyObject>>'
to 'MyApp.Program.IMyCollection'.
An explicit conversion exists (are you missing a cast?)
好的,所以我很接近.或许明确地投射?所以我将GetCollection中的return语句更改为
return (IMyCollection)b.AsReadOnly();
编译,虽然有一个resharper警告:可疑演员:解决方案中没有类型继承自’System.Collections.ObjectModel.ReadOnlyCollection>’和’MyApp.Program.IMyCollection’
在运行时,我得到一个无效的强制转换异常:无法转换类型为’System.Collections.ObjectModel.ReadOnlyCollection1 [System.Collections.Generic.IReadOnlyList1 [MyApp.Program MyObject]]’的对象以输入’IMyCollection’.
好的,我可以接受这一切.我是最后一个询问协方差和逆变等事情的人.但肯定有一种方法可以定义和创建一个具有短名称的对象,以代表一个非常长的命名数据类型.
如何创建一个名称非常长的类型并转换为名称非常短的类型?
更新:
一位同事建议使用using语句.
using IMyCollection= System.Collections.Generic.IReadOnlyList<System.Collections.Generic.IReadOnlyList<MyApp.Program.MyObject>>;
虽然这样可行,但在每个使用IMyCollection的文件中都有必要这样做.不完全是我认为我的目标的解决方案.
解决方法:
你有多想要这个?
您可以手动实现自己的包装类.
public interface IMyCollection : IReadOnlyList<IReadOnlyList<MyObject>>
{
}
public class MyCollectionImpl : IMyCollection
{
private readonly IReadOnlyList<IReadOnlyList<MyObject>> _wrappedCollection;
public MyCollectionImpl(IReadOnlyList<IReadOnlyList<MyObject>> wrappedCollection)
{
_wrappedCollection = wrappedCollection;
}
public int Count
{
get
{
return _wrappedCollection.Count;
}
}
public IReadOnlyList<MyObject> this[int index]
{
get
{
return _wrappedCollection[index];
}
}
public IEnumerator<IReadOnlyList<MyObject>> GetEnumerator()
{
return _wrappedCollection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _wrappedCollection.GetEnumerator();
}
}
然后你只需创建一个这样的实例:
public class MyObject
{
public static IMyCollection GetCollection()
{
var a = new List<MyObject>();
a.Add(new MyObject());
var b = new List<IReadOnlyList<MyObject>>();
b.Add(a.AsReadOnly());
return new MyCollectionImpl(b.AsReadOnly());
}
}
这似乎是很多额外的工作,但我实际上认为这是一个重构步骤.
我认为需要传递由复杂的通用参数组成的类型,实际上是代码中的难闻气味.
问问自己,你实际上在使用IMyCollection是什么?您是否可以在此界面中添加一些专门的方法以使其更易于使用?
一旦创建了自己的MyCollectionImpl类,就可以慢慢地向IMyCollection接口添加许多方法以简化其使用.在某些时候,您甚至可能会进入可以停止公开< IReadonlyList< IReadonlyList< MyObject>>的阶段.接口.
标签:c,casting,generic-collections 来源: https://codeday.me/bug/20190612/1223498.html