Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.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-列表是否可以无缝转换为列表或类似文件?_C#_Generics_List_.net 2.0_Casting - Fatal编程技术网

C# C-列表是否可以无缝转换为列表或类似文件?

C# C-列表是否可以无缝转换为列表或类似文件?,c#,generics,list,.net-2.0,casting,C#,Generics,List,.net 2.0,Casting,我的控件中有一个数据源,它始终是一个列表,T必须从该列表继承 基本上,我需要一些方法来完成以下工作: List<IEntity> wontWork = (List<IEntity>)this.DataSource; List<IEntity> interfaceList = this.GetDataSourceAsAnotherType<IEntity>(); int dataSourceCount = this.DataSource.Count

我的控件中有一个数据源,它始终是一个列表,T必须从该列表继承

基本上,我需要一些方法来完成以下工作:

List<IEntity> wontWork = (List<IEntity>)this.DataSource;
List<IEntity> interfaceList = this.GetDataSourceAsAnotherType<IEntity>();
int dataSourceCount = this.DataSource.Count;   // Equals 5
int interfaceCount = interfaceList.Count;      // Equals 5

interfaceList.RemoveAt(0);
int dataSourceCount = this.DataSource.Count;   // Equals 4
int interfaceCount = interfaceList.Count;      // Equals 4
另外,我不介意这是否意味着我必须使用不同的类型而不是列表


编辑:抱歉,我忘了说我正在使用.Net2.0,无法移动到.NET3.5。

好的,这可能完全不重要,但是,使用一点Linq怎么样

var interfaceList = objectList.ConvertAll<Interface>(o => (Interface)o);
这样,您可以轻松地强制转换objectList。
希望这有助于找到解决方案……

我也支持linq,但您可以这样做:

var interfaceList = objectList.Cast<IEntity>();

如果允许这样做,那将是一个非常糟糕的主意,这就是为什么不允许这样做。我可以将任何旧的元素添加到一个列表中,如果该元素不能被转换为t,该列表将爆炸。虽然所有的t都是元素,但并非所有的元素都是t


这适用于数组,因为数组像在Java中一样,有一个故意的子类型漏洞。集合没有子类型孔。

创建无缝转换的包装类。未经测试的样本:

public class CastList<TTarget, TOriginal> 
  : IList<TTarget> where TOriginal : TTarget
{
  List<TOriginal> _orig;
  public CastList(List<TOriginal> orig) { _orig = orig; }

  public Add(TTarget item) { _orig.Add(item); }

  public TTarget this[int i] 
  {
    get { return (TTarget)_orig[i]; }
    set { _orig[i] = value; }
  }

  public IEnumerator<TTarget> GetEnumerator() 
  {
     foreach(TOriginal item in _orig)
       yield return (TTarget)item;
  }

  // etc...
}

原始列表的操作也将反映在包装器中。要使用它,只需使用您的数据源构建它。

DrPizza所说的,但需要更多的代码:

public class ListFacade<TIn, TOut> : IList<TOut> where TIn : TOut
{
    private readonly IList<TIn> innerList;

    public ListFacade(IList<TIn> innerList)
    {
        this.innerList = innerList;
    }

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

    public bool IsReadOnly
    {
        get { return this.innerList.IsReadOnly; }
    }

    public TOut this[int index]
    {
        get { return this.innerList[index]; }
        set { this.innerList[index] = (TIn)value; }
    }

    public void Add(TOut item)
    {
        this.innerList.Add((TIn)item);
    }

    public void Clear()
    {
        this.innerList.Clear();
    }

    public bool Contains(TOut item)
    {
        return (item is TIn) && this.innerList.Contains((TIn)item);
    }

    public void CopyTo(TOut[] array, int arrayIndex)
    {
        var inArray = new TIn[this.innerList.Count];
        this.innerList.CopyTo(inArray, arrayIndex);
        Array.Copy(inArray, array, inArray.Length);
    }

    public IEnumerator<TOut> GetEnumerator()
    {
        foreach (var item in this.innerList)
        {
            yield return item;
        }
    }

    System.Collections.IEnumerator
        System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    public int IndexOf(TOut item)
    {
        return (item is TIn) ? this.innerList.IndexOf((TIn)item) : -1;
    }

    public void Insert(int index, TOut item)
    {
        this.innerList.Insert(index, (TIn)item);
    }

    public bool Remove(TOut item)
    {
        return (item is TIn) && this.innerList.Remove((TIn)item);
    }

    public void RemoveAt(int index)
    {
        this.innerList.RemoveAt(index);
    }

如果参数不是TIn类型,则Add、Insert和indexer集将爆炸。

对不起,我使用的是.Net2.0,我忘了指定。@Roel,@GenericTypeTea:ConvertAll与LINQ无关,它是列表本身的一个方法,在.Net2中可用,但如果没有C3,则需要使用旧的委托语法,而不是lambda。但是ConvertAll并不满足要求,因为它返回一个新列表,而不是对现有列表进行就地转换。感谢您的解释。我知道ConvertAll存在于列表中,但我已经尝试过了,并且知道它不符合您所指出的我的要求;除了别的,你应该考虑将数据源改为ILIST而不是列表。@ DrPizza,+ 1,我第一次听到.NET程序员说的话!我正在使用.Net2.0。因此我不能使用linq。@klausbyskov:这不符合要求,因为它返回一个新列表,而不是对现有列表进行就地转换。嗯,好的。。。然后嗯。。。你能把它扔给一个数不清的人吗?我有一些代码正是这样做的,这是有效的。。。但我在这里的.NET4国家,所以我不知道是否有一些新的和闪光的东西,我不知道。啊,当然。对于你为什么不能这样做,现在有了完美的解释。谢谢你的建议。关于我能做些什么,有什么建议吗?复制到列表中,然后再复制回来。如果您不需要可扩展性,只需更换元素就可以了。虽然没有数组子类型漏洞那么糟糕,但我仍然不确定这是否真的应该鼓励。我认为这取决于用例。我不建议这样设计一个框架,但如果它只是将一些类粘在一起的一个实现细节,为什么不呢?我真正的问题是,为什么DataSource不只是一个列表呢?如果他想把它们当作简单的工具,而不使用任何特定于T的方法,那么首先将它们存储在列表中似乎更容易。
public class CastList<TTarget, TOriginal> 
  : IList<TTarget> where TOriginal : TTarget
{
  List<TOriginal> _orig;
  public CastList(List<TOriginal> orig) { _orig = orig; }

  public Add(TTarget item) { _orig.Add(item); }

  public TTarget this[int i] 
  {
    get { return (TTarget)_orig[i]; }
    set { _orig[i] = value; }
  }

  public IEnumerator<TTarget> GetEnumerator() 
  {
     foreach(TOriginal item in _orig)
       yield return (TTarget)item;
  }

  // etc...
}
public class ListFacade<TIn, TOut> : IList<TOut> where TIn : TOut
{
    private readonly IList<TIn> innerList;

    public ListFacade(IList<TIn> innerList)
    {
        this.innerList = innerList;
    }

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

    public bool IsReadOnly
    {
        get { return this.innerList.IsReadOnly; }
    }

    public TOut this[int index]
    {
        get { return this.innerList[index]; }
        set { this.innerList[index] = (TIn)value; }
    }

    public void Add(TOut item)
    {
        this.innerList.Add((TIn)item);
    }

    public void Clear()
    {
        this.innerList.Clear();
    }

    public bool Contains(TOut item)
    {
        return (item is TIn) && this.innerList.Contains((TIn)item);
    }

    public void CopyTo(TOut[] array, int arrayIndex)
    {
        var inArray = new TIn[this.innerList.Count];
        this.innerList.CopyTo(inArray, arrayIndex);
        Array.Copy(inArray, array, inArray.Length);
    }

    public IEnumerator<TOut> GetEnumerator()
    {
        foreach (var item in this.innerList)
        {
            yield return item;
        }
    }

    System.Collections.IEnumerator
        System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    public int IndexOf(TOut item)
    {
        return (item is TIn) ? this.innerList.IndexOf((TIn)item) : -1;
    }

    public void Insert(int index, TOut item)
    {
        this.innerList.Insert(index, (TIn)item);
    }

    public bool Remove(TOut item)
    {
        return (item is TIn) && this.innerList.Remove((TIn)item);
    }

    public void RemoveAt(int index)
    {
        this.innerList.RemoveAt(index);
    }