C# 列表<;字符串>;传地址

C# 列表<;字符串>;传地址,c#,C#,我想知道如何证明.Net框架在幕后做了什么 我有一个方法,它接受列表originalParameterList的参数 在我的方法中,如果我执行以下操作,则会有另一个列表newListObj: List<String> newListObj = originalParameterList newListObj.Add(value); newListObj.Add(value1); newListObj.Add(value2); List newListObj=

我想知道如何证明.Net框架在幕后做了什么

我有一个方法,它接受
列表originalParameterList
的参数

在我的方法中,如果我执行以下操作,则会有另一个
列表newListObj

List<String> newListObj = originalParameterList
    newListObj.Add(value);
    newListObj.Add(value1);
    newListObj.Add(value2);
List newListObj=originalParameterList
新增(价值);
newListObj.Add(值1);
newListObj.Add(值2);
原始参数列表的计数增加(+3)

如果我这样做:

List<String> newListObj = new List<String>(originalParamterList);

newListObj.Add(value);
newListObj.Add(value1);
newListObj.Add(value2);
List newListObj=新列表(原始参数列表);
新增(价值);
newListObj.Add(值1);
newListObj.Add(值2);
原始参数列表的计数保持不变(+0)

我还发现此代码的行为与此相同:

List<String> newListObj = new List<String>(originalParamterList.ToArray());

newListObj.Add(value);
newListObj.Add(value1);
newListObj.Add(value2);
List newListObj=新列表(originalParameterList.ToArray());
新增(价值);
newListObj.Add(值1);
newListObj.Add(值2);
原始参数列表的计数保持不变(+0)


我的问题是,有没有一种方法可以明确地看到.Net Framework在幕后做了什么?

通常,文档应该提供足够的信息来使用API

在您的特定示例中,
public List(IEnumerable collection)
的文档说明(emphasis mine):

初始化包含元素的List类的新实例 从指定集合复制了,并具有足够的容量 容纳复制的元素数

以下是构造函数的源代码供参考:

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

    // initialize to needed size (if determinable)
    ICollection <T> c = collection as ICollection <T>;
    if (c == null) {
        _items = EmptyArray<T>.Value;;
        AddEnumerable (collection);
    } else {
        _size = c.Count;
        _items = new T [Math.Max (_size, DefaultCapacity)];
        c.CopyTo (_items, 0);
    }
}

void AddEnumerable (IEnumerable <T> enumerable)
{
    foreach (T t in enumerable)
    {
        Add (t);
    }
}
公共列表(IEnumerable集合)
{
if(集合==null)
抛出新的ArgumentNullException(“集合”);
//初始化为所需大小(如果可确定)
ICollection c=作为ICollection的集合;
如果(c==null){
_items=EmptyArray.Value;;
可加数(集合);
}否则{
_尺寸=c.计数;
_项目=新T[数学最大值(_大小,默认容量)];
c、 复制到(_项,0);
}
}
void AddEnumerable(IEnumerable可枚举)
{
foreach(可枚举中的T)
{
加(t);
}
}

最简单的方法就是访问MSDN

上面说

初始化List类的新实例,该实例包含从指定集合复制的元素,并具有足够的容量来容纳复制的元素数

因此,在内部,只需将传递的IEnumerable的所有元素添加到新列表中即可。它还说

这是一个O(n)操作


这意味着没有进行任何优化。

这是因为在第一种情况下,您引用了原始列表(因为它是引用类型),并且通过newListObj修改了它的集合。第二种和第三种情况是,您通过列表构造函数复制了原始对象的集合,并修改了新集合,这不会对原始集合产生任何影响。

正如其他人所说,有各种工具可以让您检查.NET framework的源代码。我个人更喜欢免费的

在您提到的特定情况下,我认为当您将一个列表传递给另一个列表的构造函数时,该列表将被复制。如果您只是将一个变量分配给另一个变量,那么这些变量只是引用同一个列表。

您可以

  • 反编译生成的MSIL代码,例如使用
  • 或者

这是列表构造函数的代码:

public List(IEnumerable<T> collection)
{
    if (collection == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
    }
    ICollection<T> collection2 = collection as ICollection<T>;
    if (collection2 != null)
    {
        int count = collection2.Count;
        this._items = new T[count];
        collection2.CopyTo(this._items, 0);
        this._size = count;
        return;
    }
    this._size = 0;
    this._items = new T[4];
    using (IEnumerator<T> enumerator = collection.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            this.Add(enumerator.Current);
        }
    }
}
公共列表(IEnumerable集合)
{
if(集合==null)
{
ThrowHelper.ThrowArgumentNullException(argument.collection除外);
}
ICollection collection2=作为ICollection的集合;
if(collection2!=null)
{
int count=collection2.count;
此._items=新的T[计数];
collection2.CopyTo(此._项,0);
这个。_size=count;
返回;
}
这个。_size=0;
此._items=新T[4];
使用(IEnumerator枚举器=collection.GetEnumerator())
{
while(枚举数.MoveNext())
{
this.Add(枚举数.Current);
}
}
}

正如您在调用接受IEnumerable的costructor时所看到的,它会将所有数据复制到自身。

您可以将程序集加载到ILDASM中,然后(加载时)找到您的方法并双击它, 它将显示该方法的cil代码。只需在windows开始菜单中的搜索中键入“IL”

或者,您也可以使用以下方法创建一个新的独立列表

        private void GetList(List<string> lst)
        {
            List<string> NewList = lst.Cast<string>().ToList();
            NewList.Add("6");
            //not same values.
            //or....
            List<string> NewList = lst.ConvertAll(s => s);
            NewList.Add("6");
            //again different values

        }
private void GetList(List lst)
{
List NewList=lst.Cast().ToList();
新列表。添加(“6”);
//不同的值。
//或者。。。。
List NewList=lst.ConvertAll(s=>s);
新列表。添加(“6”);
//又是不同的价值观
}

您可以检查IL。此外,在创建新列表时,您正在传递对该列表的引用。您没有影响原始列表。请仔细阅读。例如,您也可以使用反射器。另一个资源是。请看,由于使用了“new”关键字,因此这里有一个新对象,这一点非常清楚。您可以检查语法并确定它在做什么。“新建”将创建一个新对象。And=将创建一个引用。