Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C#中的泛型列表和接口进行类型转换-寻找优雅的解决方案_C#_Generics_Type Conversion - Fatal编程技术网

使用C#中的泛型列表和接口进行类型转换-寻找优雅的解决方案

使用C#中的泛型列表和接口进行类型转换-寻找优雅的解决方案,c#,generics,type-conversion,C#,Generics,Type Conversion,以下面的示例(创建此示例纯粹是为了演示这一点)。我试图做的是将系统的一个部分与另一个部分隔离开来,并且只想从程序集外部公开功能的特定子集,同时在内部使用full objects方法 这段代码可以编译,但我在运行时得到一个无效的强制转换异常。感觉这应该行得通,但不幸的是不行 谁能为这个问题提出一个优雅的解决方案 更新:根据评论,我已更改此示例以更好地演示此问题,我还在示例中显示了对我有效的解决方案 using System.Collections.Generic; namespa

以下面的示例(创建此示例纯粹是为了演示这一点)。我试图做的是将系统的一个部分与另一个部分隔离开来,并且只想从程序集外部公开功能的特定子集,同时在内部使用full objects方法

这段代码可以编译,但我在运行时得到一个无效的强制转换异常。感觉这应该行得通,但不幸的是不行

谁能为这个问题提出一个优雅的解决方案

更新:根据评论,我已更改此示例以更好地演示此问题,我还在示例中显示了对我有效的解决方案

    using System.Collections.Generic;

    namespace Test
    {
        public class PeopleManager
        {
            List<Person> people = new List<Person>();

            public PeopleManager()
            {
            }

            public void CreatePeople()
            {               
                people.Add(new Person("Joe", "111 aaa st"));
                people.Add(new Person("Bob", "111 bbb st"));
                people.Add(new Person("Fred", "111 ccc st"));
                people.Add(new Person("Mark", "111 ddd st"));                
            }

            public IList<IName> GetNames()
            {
                /* ERROR
                 * Cannot convert type 'System.Collections.Generic.List<Test.Person>' 
                 * to 'System.Collections.Generic.List<Test.IName>' c:\notes\ConsoleApplication1\Program.cs
                 */

                return (List<IName>) people; // <-- Error at this line

                // Answered my own question, do the following

                return people.ConvertAll(item => (IName)item);
            }
        }

        public interface IName
        {
            string Name { get; set; }
        }

        internal class Person : IName
        {
            public Person(string name, string address)
            {
                this.Name = name;
                this.Address = address;
            }

            public string Name
            {
                get;
                set;
            }

            public string Address
            {
                get;
                set;
            }
        }
    }
使用System.Collections.Generic;
名称空间测试
{
公共班级人事经理
{
列表人员=新列表();
公共人事经理()
{
}
公众人物()
{               
人物。添加(新人物(“乔”,“111 aaa街”);
新增(新人员(“鲍勃”,“111 bbb街”);
人员。添加(新人员(“Fred”、“111 ccc st”);
人员。添加(新人员(“Mark”,“111 ddd st”);
}
公共IList GetNames()
{
/*错误
*无法转换类型“System.Collections.Generic.List”
*至“System.Collections.Generic.List”c:\notes\ConsoleApplication1\Program.cs
*/
返回(列表)人员;//(IName)项目);
}
}
IName公共接口
{
字符串名称{get;set;}
}
内部类人员:IName
{
公众人物(字符串名称、字符串地址)
{
this.Name=Name;
这个地址=地址;
}
公共字符串名
{
得到;
设置
}
公共字符串地址
{
得到;
设置
}
}
}
IList restricted=people.Cast().ToList();
IList restricted=people.Cast().ToList();

继承自
IName
,但
列表
不继承自
列表
。想象一下,如果它这样做了:您可以将一个
列表
投射到它的超类
列表
,然后添加一个
IName
的实例,该实例不是
Person
的实例


只需将您的
列表
设为
列表
——这就足够了。

个人
继承自
IName
,但
列表
不继承自
列表
。想象一下,如果它这样做了:您可以将一个
列表
投射到它的超类
列表
,然后添加一个
IName
的实例,该实例不是
Person
的实例


只要把你的
列表
列成一个
列表就足够了。

回答了我自己的问题,但我想我会发帖,以防将来有人碰到这个问题。在发生错误的那一行,您实际上可以这样做,这非常漂亮:

List<IName> restricted = people.ConvertAll(item => (IName) item); 
List restricted=people.ConvertAll(item=>(IName)item);

回答了我自己的问题,但我想我会发帖,以防将来有人碰到这个问题。在发生错误的那一行,您实际上可以这样做,这非常漂亮:

List<IName> restricted = people.ConvertAll(item => (IName) item); 
List restricted=people.ConvertAll(item=>(IName)item);

我会创建一个类来包装一个集合(为了性能),而不是像页面上的其他解决方案那样复制

public class CovariantList<TType, TBase> : IList<TBase>
where TType:TBase,class
{
private IList<TType> _innerList;

public int Count
{
get
{
return this._innerList.Count;
}
}

public TBase this[int index]
{
get
{
return this._innerList[index];
}
set
{
TType type = value as TType;
if(type!=null)
{
...
}
}
...
公共类协方差列表:IList
其中TType:TBase,class
{
私有IList_内部列表;
公共整数计数
{
得到
{
返回此。\u innerList.Count;
}
}
公共t基于此[int索引]
{
得到
{
返回此。_innerList[索引];
}
设置
{
TType type=作为TType的值;
if(type!=null)
{
...
}
}
...

我会创建一个类来包装一个集合(为了性能),而不是像页面上的其他解决方案那样复制

public class CovariantList<TType, TBase> : IList<TBase>
where TType:TBase,class
{
private IList<TType> _innerList;

public int Count
{
get
{
return this._innerList.Count;
}
}

public TBase this[int index]
{
get
{
return this._innerList[index];
}
set
{
TType type = value as TType;
if(type!=null)
{
...
}
}
...
公共类协方差列表:IList
其中TType:TBase,class
{
私有IList_内部列表;
公共整数计数
{
得到
{
返回此。\u innerList.Count;
}
}
公共t基于此[int索引]
{
得到
{
返回此。_innerList[索引];
}
设置
{
TType type=作为TType的值;
if(type!=null)
{
...
}
}
...
IList restricted=people.ToList();
略短于

IList<IName> restricted = people.Cast<IName>().ToList(); 
IList restricted=people.Cast().ToList();
IList restricted=people.ToList();
略短于

IList<IName> restricted = people.Cast<IName>().ToList(); 
IList restricted=people.Cast().ToList();

请只包含与您的问题直接相关的snippits好吗?它必须是
IList
?它可以是
IEnumerable
?嘿,伙计们,如果这不清楚的话,很抱歉,但我在这里选择的原因是因为类,我代码中这个实例中的人有1000行专有逻辑。在实现程序集我希望访问类的所有功能。但是在程序集之外,我只想公开类客户机特定接口……这样做对我来说非常有用:List restricted=people.ConvertAll(item=>(IName)item);我想我也会分享这一点,因为它与域映射问题有关。我发现了一个名为AutoMapper的项目,在更大范围内可能是一个更好的解决方案。下面是更多信息的链接:你能不能只包括与你的问题直接相关的snippits?它必须是
IList
?它可以是一个
IEnumerable
?嘿,伙计们,如果这不清楚的话,很抱歉,但我在这里强制转换的原因是因为类,我代码中这个实例中的人有1000行专有逻辑。在实现程序集中,我希望访问类的所有功能。但是