为什么ObservableCollection <t>有两个集合构造函数?

时间:2015-10-30 14:37:48

标签: c#

ObservableCollection(T)类有两个构造函数,可以在其中传递项集合。一个构造函数接受IEnumerable(T),另一个构建函数接受List(T)

鉴于List(T)实现IEnumerable(T),为什么第二个构造函数存在?

2 个答案:

答案 0 :(得分:3)

在.NET 3.0中引入了带List的构造函数,而在.NET 3.5中引入了带IEnumerable的构造函数,因此删除List构造函数会有制动改变了。

我的猜测是他们把它写成List,然后发货,然后意识到它可能更为通用。

source code也有一个有趣的评论(不确定它是否相关):

    public ObservableCollection(List<T> list)
        : base((list != null) ? new List<T>(list.Count) : list)
    {
        // Workaround for VSWhidbey bug 562681 (tracked by Windows bug 1369339).
        // We should be able to simply call the base(list) ctor.  But Collection<T>
        // doesn't copy the list (contrary to the documentation) - it uses the
        // list directly as its storage.  So we do the copying here.
        // 
        CopyFrom(list);
    }

    public ObservableCollection(IEnumerable<T> collection)
    {
        if (collection == null)
            throw new ArgumentNullException("collection");

        CopyFrom(collection);
    }

答案 1 :(得分:1)

在这里看一下来源:

http://referencesource.microsoft.com/#System/compmod/system/collections/objectmodel/observablecollection.cs,f63ea2601f5edbbb

如果不深入挖掘,你会注意到这一点:

public ObservableCollection(List<T> list)
    : base((list != null) ? new List<T>(list.Count) : list)
{
    // Workaround for VSWhidbey bug 562681 (tracked by Windows bug 1369339).
    // We should be able to simply call the base(list) ctor.  But Collection<T>
    // doesn't copy the list (contrary to the documentation) - it uses the
    // list directly as its storage.  So we do the copying here.
    // 
    CopyFrom(list);
}

而且:

public ObservableCollection(IEnumerable<T> collection)
{
    if (collection == null)
        throw new ArgumentNullException("collection");

    CopyFrom(collection);
}

请注意,在传递List<T>的情况下,它会使用新的List<T>调用基础构造函数,并且其容量已设置为与您传入的列表的Count相匹配。显然,您由于IEnumerable<T>没有IEnumerable<T>属性,因此Count无法执行此操作。所以它看起来像一个优化。如果您已经知道集合的大小,那么当您将源复制到内部List<T>时,可以避免因内部#region Assembly WindowsBase.dll, v3.0.0.0 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll #endregion using System; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; namespace System.Collections.ObjectModel { [Serializable] public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged { public ObservableCollection(); public ObservableCollection(IEnumerable<T> collection); public ObservableCollection(List<T> list); //.... 的大小而受到惩罚。

编辑:也是@DStanley关于改变的观点。无论如何,这可能更重要。 再次编辑:或者可能不是,因为文档似乎有些混乱。但我创建了一个针对.NET 3.0的项目,似乎两个构造函数都在那里。如果我在Visual Studio中使用“转到定义”,我可以看到:

var list = new List<int>() {1,2,3};
IEnumerable<int> enumerable = (IEnumerable<int>)list;
var obsWithList = new ObservableCollection<int>(list);
var obsWithEnumerable = new ObservableCollection<int>(enumerable);

这个代码在.NET 3.0中编译得很好:

var internalListProp = typeof(ObservableCollection<int>).GetProperty("Items", BindingFlags.NonPublic | BindingFlags.Instance);

var l0 = (internalListProp.GetValue(obsWithList, null) as List<int>).Capacity;        // 3
var l1 = (internalListProp.GetValue(obsWithEnumerable, null) as List<int>).Capacity;  // 4

稍作反思:

Count

您可以看到内部列表的容量设置为在传递List<T>时与IEnumerable<T>匹配,但在 $scope.getImage=function(a){ $http({method: 'GET', url: 'http://url/provawp/api/user/get_avatar/?user_id=' + a + '&type=full'}). success(function(data, status, headers, config) { console.log("id-autore" + a); var img=data.avatar; var element = $('<div>').html(img); $scope.source = element.find('img').attr("src"); return $scope.source; console.log("immagine" + $scope.source); }). error(function(data, status, headers, config) { console.log("errore avatar"); }); }; 传递时则不符。