编程语言
首页 > 编程语言> > c# – 为复杂泛型类型创建类或接口

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