C# 为复杂泛型类型创建类或接口

C# 为复杂泛型类型创建类或接口,c#,casting,generic-collections,C#,Casting,Generic Collections,我正在尝试为对象列表的类型创建别名。具体而言,我想缩短此类型的所有键入时间: IReadOnlyList<IReadOnlyList<MyObject>> 这将编译,尽管带有一个重拾器警告:可疑强制转换:解决方案中没有从“System.Collections.ObjectModel.ReadOnlyCollection>”和“MyApp.Program.IMyCollection”继承的类型 在运行时,我得到一个无效的强制转换异常:无法将类型为“System.Colle

我正在尝试为对象列表的类型创建别名。具体而言,我想缩短此类型的所有键入时间:

IReadOnlyList<IReadOnlyList<MyObject>>
这将编译,尽管带有一个重拾器警告:可疑强制转换:解决方案中没有从“System.Collections.ObjectModel.ReadOnlyCollection>”和“MyApp.Program.IMyCollection”继承的类型

在运行时,我得到一个无效的强制转换异常:无法将类型为“System.Collections.ObjectModel.ReadOnlyCollection
1[System.Collections.Generic.IReadOnlyList
1[MyApp.Program+MyObject]]”的对象强制转换为类型“IMyCollection”

好的,我可以接受这一切。我是最后一个问协方差和逆变等问题的人。但是肯定有一种方法可以定义和创建一个具有短名称的对象来代表一个非常长的命名数据类型

如何创建一个名称很长的类型并转换为一个名称很短的类型

更新: 一位同事建议使用
语句

using IMyCollection= System.Collections.Generic.IReadOnlyList<System.Collections.Generic.IReadOnlyList<MyApp.Program.MyObject>>;
使用IMyCollection=System.Collections.Generic.IReadOnlyList;

虽然这样做可行,但在使用
IMyCollection
的每个文件中都必须这样做。不完全是我认为我的目标的解决方案。

< P>这与协方差无关。code>IMyCollection
继承自
IReadOnlyList
,因此您可以将
IMyCollection
的实例强制转换为
IReadOnlyList
,但不能反过来


如果您想进行一些自定义转换,那么可以使用所需的短名称创建一个类型,并使用声明从
IReadOnlyList
到您的类型的转换。使用运算符重载似乎确实是不必要和不寻常的,但这是实现您想要实现的目标的唯一方法。

您有多希望这样做

您可以手动实现自己的包装器类

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();
    }
}
公共接口IMyCollection:IReadOnlyList
{
}
公共类MyCollectionImpl:IMyCollection
{
私有只读IReadOnlyList\u wrappedCollection;
公共MyCollectionImpl(IReadOnlyList wrappedCollection)
{
_wrappedCollection=wrappedCollection;
}
公共整数计数
{
得到
{
返回_wrappedCollection.Count;
}
}
公共IReadOnlyList此[int索引]
{
得到
{
返回_wrappedCollection[索引];
}
}
公共IEnumerator GetEnumerator()
{
返回_wrappedCollection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
返回_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());
        }
    }
公共类MyObject
{
公共静态IMyCollection GetCollection()
{
var a=新列表();
a、 添加(新的MyObject());
var b=新列表();
b、 添加(a.AsReadOnly());
返回新的MyCollectionImpl(b.AsReadOnly());
}
}

这看起来有很多额外的工作,但我会认为这是一个重构步骤。 我认为,需要传递由一组复杂的泛型参数组成的类型,这实际上是代码中的一种不好的味道

扪心自问,您实际使用IMyCollection的目的是什么?您是否可以向该接口添加一些专门的方法以使其更易于使用


一旦您创建了自己的
MyCollectionImpl
类,您就可以慢慢地向
IMyCollection
接口添加许多方法,以简化其使用。在某个时候,您甚至可能会达到这样一个阶段,即您可以停止公开
,因为您使用的是
var
,为什么您需要它更短?您也在使用list,只需调用
AsReadOnly
方法“我想保存击键,”当然,更改对象模型似乎不是一个好理由-如果您尝试的操作成功,您将禁止我在我指定的所有位置使用任何不是
IMyCollection
IReadOnlyList
,即使你的意图是它们是相同的。@devestation你关注的是一个简单的例子,这个例子只是为了演示我正在尝试的演员阵容。在现实世界中,完整类型必须作为函数返回值多次输入,作为参数传递给其他函数,在从数据包检索时强制转换,等等。这正是我的想法。这确实是对我的代码的重构,每次只需一小步,就可以根据需要添加特性。我的问题是想在仅仅使用复杂类型和实现MyCollectionImpl之间找到一步。谢谢你的回答!
using IMyCollection= System.Collections.Generic.IReadOnlyList<System.Collections.Generic.IReadOnlyList<MyApp.Program.MyObject>>;
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());
        }
    }