新足迹

 找回密码
 注册

精华好帖回顾

· 回首来澳三周年,我的学习/工作小总结 (2013-11-1) 马二小 · 《参加活动》我的模型收藏-----男人的想像空间。 (2013-2-12) 老树子
· 不经历风雨,怎么见彩虹——成长的烦恼:校园bully——遇到问题儿童怎么办?#194 (2017-2-28) 小小白虎 · 西班牙海鲜饭试验版 (2005-12-23) 小米
Advertisement
Advertisement
楼主:自由的心

弱弱地问一下 C# System.Collection.Generic.List<T> [复制链接]

头像被屏蔽

禁止访问

发表于 2012-1-9 22:42 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
其实C# 4.0 in a nutshell (4th edition) 这本书还是比较好的,浅显易懂,适合中级业余兴趣爱好者,900多页能全部理解也能对C#有一定心得......
Advertisement
Advertisement
头像被屏蔽

禁止访问

发表于 2012-1-9 22:45 |显示全部楼层
此文章由 atransformer 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 atransformer 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 自由的心 于 2012-1-9 23:23 发表


这是List Initializer,和object initializer差不多,在CLR 2.0 SP1 (即.NET Framework version 3.5)后才有的......


哎,学了不用,都忘了。
头像被屏蔽

禁止访问

发表于 2012-1-9 22:50 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
数了一下,C# 4.0 in a nutshell 正文995页,到现在还没有全部搞定......
头像被屏蔽

禁止访问

发表于 2012-1-9 22:56 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 金靴 于 2012-1-9 23:34 发表
感觉好像都是学生
比较基本的
1) System.Colletion.Generic.List shall be System.Colletions.Generic.List, usually "using system.x.x" instead of full qualified name
2) list2 is not null, list2 is a referenc ...


1)是当然的
顶2)......

发表于 2012-1-9 23:36 |显示全部楼层
此文章由 Brisun 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 Brisun 所有!转贴必须注明作者、出处和本声明,并保持内容完整
强调一下,在C#中说reference type是指针或地址并不准确。通常从C语言过来的程序员喜欢这么说,因为好理解。
Reference就是reference,因为有garbage collection,reference所指向的object的真正地址是会变的。一个简单的问题就牵扯到内存管理或是编译器什么的似乎也没有必要。

评分

参与人数 1积分 +1 收起 理由
自由的心 + 1 应可以用'unsafe' &amp; 'fixed' keywords ...

查看全部评分

头像被屏蔽

禁止访问

发表于 2012-1-10 19:38 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 flyspirit 于 2012-1-9 23:05 发表


就是指地址相同, 不是内容。 你可以用==比较下, C#里面==比较的是地址。 比较内容用equals。


C#里面 == 比较的是内容,不是地址

value-type objects:
double d1 = 5.0;
double d2 = d1;
if (d1 == d2)
{
    // it will go in here, 但是d1和d2的地址不同,仅仅它们的内容相同
}

reference-type objects:
public Class C
{
    private readonly bool isReferenceType;
    public C(bool isReferenceType)
    {
        this.isReferenceType = isReferenceType == true ? true : true;
    }
}
在一个method里面create reference-type objects of type C
C c1 = new C(true);
C c2 = c1; // 仅仅c1和c2的内容相同(c1 & c2 reference the same object, which means, c1 & c2 are reference-type objects which have the same value, and that value references an object of type C), 地址不同,即c1和c2在处在不同的物理地址
if (c1 == c2)
{
    // it will go in here
}
Advertisement
Advertisement
头像被屏蔽

禁止访问

发表于 2012-1-10 21:11 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
接着36楼,通过下面的method
应可以达到reference-type objects的地址也相同 (即完全相同)

public static void Main()
{
    C c1 = new C(true);
    Test(c1);
}

public static void Test(ref C c2)
{
    // 这才使c1和c2完全相同(不仅c1和c2的value相同,c1, c2本身的address也相同)
   
    // 解释得更透彻些: c1和c2处在stack上,而且address相同,c1和c2的value其实是个地址,
    // 这个地址里面的内容才是处在heap上的C object which is referenced by or pointed to by both c1 & c2.
    // 即c1和c2是处在stack上的同一个地址区间,他们所共同指向的object是处在heap上
}

[ 本帖最后由 自由的心 于 2012-1-10 22:16 编辑 ]

发表于 2012-1-10 21:46 |显示全部楼层
此文章由 无视 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 无视 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 自由的心 于 2012-1-10 22:11 发表
接着36楼,通过下面的method
应可以达到reference-type objects的地址也相同 (即完全相同)

public static void Main()
{
    C c1 = new C(true);
    Test(c1);
}

public static void Test(ref C c2)
{
    // 这才使 ...


这位tx比较好学,先赞一个!!

1. c1和c2在不同的stack,他们的地址不相同,让他们在这个级别上相同的努力是徒劳的。

2. reference type作为参数,不必用ref,value type用ref才有意义.
头像被屏蔽

禁止访问

发表于 2012-1-10 21:52 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 无视 于 2012-1-10 22:46 发表


这位tx比较好学,先赞一个!!

1. c1和c2在不同的stack,他们的地址不相同,让他们在这个级别上相同的努力是徒劳的。

2. reference type作为参数,不必用ref,value type用ref才有意义.


还是请神人出来纠正一下上述这2条吧......
头像被屏蔽

禁止访问

发表于 2012-1-10 21:55 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
value type parameter 和 reference type parameter 都可以用 ref

不用就相当于用 = 来 assign
用了ref 相当于 地址 也相同了
头像被屏蔽

禁止访问

发表于 2012-1-10 22:08 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
这么说吧

value type parameter 和 reference type parameter 都可以用 ref,用和不用的效果是不同的

不用就相当于用 = 来 assign value给parameter
用了ref 相当于 对编译器来说 把这个parameter(不管是value type 还是 reference type)看成是传进来的object (不管是value type 还是 reference type) 的 alias,意思就是完全一致了(当然他们本身地址也相同了)
Advertisement
Advertisement
头像被屏蔽

禁止访问

发表于 2012-1-10 22:23 |显示全部楼层

弱弱地问一下 C# System.Collection.Generic.List<T>

此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
我在C#里定义好这样1个class
public class SomeReferenceType
{
    int id;
    public SomeReferenceType(int id)
    {
        this.id = id;
    }
}

现在1个method里面有
......
System.Colletion.Generic.List<SomeReferenceType> list1 = new System.Colletion.Generic.List { new SomeReferenceType(1), new SomeReferenceType(2) };
System.Colletion.Generic.List<SomeReferenceType> list2 = list1; // 直接create a list2 (which is a reference-type object)
list1 = null // 现故意把list1设成null了,即list1指向null

请问现在list2里面是有2个SomeReferenceType objects, 还是说list2也指向null了?

(手头没有C#编译器,有请神人解答......)

详细请见
http://www.oursteps.com.au/bbs/viewthread.php?tid=443644&extra=page%3D1
36楼 和 37楼,请神人出手赏玩一下我的观点

[ 本帖最后由 自由的心 于 2012-1-10 23:32 编辑 ]

发表于 2012-1-10 22:28 |显示全部楼层
此文章由 fly050505 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 fly050505 所有!转贴必须注明作者、出处和本声明,并保持内容完整
画图就出来了。
list2还是指向原来的Object
头像被屏蔽

禁止访问

发表于 2012-1-10 22:32 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
详细请见36,37楼

发表于 2012-1-11 09:12 |显示全部楼层
此文章由 无视 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 无视 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 自由的心 于 2012-1-10 23:08 发表
这么说吧

value type parameter 和 reference type parameter 都可以用 ref,用和不用的效果是不同的

不用就相当于用 = 来 assign value给parameter
用了ref 相当于 对编译器来说 把这个parameter(不管是value type  ...


得弄清楚在call method的时候,传递参数到底发生了什么。

从compiler这个角度,如果没有ref,无论是value type 还是reference type,caller pass过来的parameters是原封不同的copy && push stack到callee.

如果有ref,callee的参数是指向caller参数的reference,或者说指针,同样根是否value/reference type无关。

在实际应用中,ref当然可以用在reference type上,没有疑义,但意义不大,因为callee中的改变完全反应在caller中,但对value type来说用了ref就不用return result, 这是ref/out实际意义所在。

out of box, 比较两个variable的值(无论是reference type还是value type)有意义,比较它们本身在内存中的位置没有意义,也不可能相同。

发表于 2012-1-11 10:33 |显示全部楼层
此文章由 wil 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 wil 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 自由的心 于 2012-1-10 22:11 发表
接着36楼,通过下面的method
应可以达到reference-type objects的地址也相同 (即完全相同)

public static void Main()
{
    C c1 = new C(true);
    Test(c1);
}

public static void Test(ref C c2)
{
    // 这才使c1和c2完全相同(不仅c1和c2的value相同,c1, c2本身的address也相同)
   
    // 解释得更透彻些: c1和c2处在stack上,而且address相同,c1和c2的value其实是个地址,
    // 这个地址里面的内容才是处在heap上的C object which is referenced by or pointed to by both c1 & c2.
    // 即c1和c2是处在stack上的同一个地址区间,他们所共同指向的object是处在heap上
}


http://msdn.microsoft.com/en-us/library/0f66670z%28VS.71%29.aspx
看看Example 2: Passing Value Types by Reference的Code Discussion:
“In this example, it is not the value of myInt that is passed; rather, a reference to myInt is passed. The parameter x is not an int; it is a reference to an int (in this case, a reference to myInt). Therefore, when x is squared inside the method, what actually gets squared is what x refers to: myInt.”
这句话说明,你的例子中的c1和c2地址是应该不同的,c2是指向c1的reference

[ 本帖最后由 wil 于 2012-1-11 11:35 编辑 ]
回忆是红色的天空
Advertisement
Advertisement

发表于 2012-1-11 10:51 |显示全部楼层
此文章由 wil 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 wil 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 无视 于 2012-1-10 22:46 发表


这位tx比较好学,先赞一个!!

1. c1和c2在不同的stack,他们的地址不相同,让他们在这个级别上相同的努力是徒劳的。

2. reference type作为参数,不必用ref,value type用ref才有意义.


还是根据http://msdn.microsoft.com/en-us/library/0f66670z%28VS.71%29.aspx里的Example 5: Passing Reference Types by Reference这个例子
“Code Discussion

All of the changes that take place inside the method affect the original array in Main. In fact, the original array is reallocated using the new operator. Thus, after calling the Change method, any reference to myArray points to the five-element array, which is created in the Change method.”
所以你的第2个观点是不对的,ref对于reference type同样有意义,没有ref的话,就和java的传入mutable object效果一样,是传入了object reference的copy,但在C#里的这个ref关键字,可以做到java做不到的事,就是方法参数实际是指向入参变量reference的reference

但你说的不必纠结具体内存地址分配这个我支持,因为官方可以用相同的地址来实现ref,也可以用不同的内存地址实现,我们只要知道ref的使用规则就好了,不用考虑具体实现问题
回忆是红色的天空

发表于 2012-1-11 12:47 |显示全部楼层
此文章由 无视 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 无视 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 wil 于 2012-1-11 11:51 发表


还是根据http://msdn.microsoft.com/en-us/library/0f66670z%28VS.71%29.aspx里的Example 5: Passing Reference Types by Reference这个例子
“Code Discussion

All of the changes that take place inside the m ...



good point!!

我应该修正一下如果想修改reference type object时用不用ref没所谓,那个例子new了一下....

发表于 2012-1-11 13:34 |显示全部楼层
此文章由 hornsay 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 hornsay 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 无视 于 2012-1-11 13:47 发表



good point!!

我应该修正一下如果想修改reference type object时用不用ref没所谓,那个例子new了一下....

对。

我没有研究过C#, 但是在Delphi里,pass object or pass object  as ref都是一样的,他们都是pass 地址. pass as reference 只有在integer, float, string等上有区别。
持不同股见者...
头像被屏蔽

禁止访问

发表于 2012-1-11 19:47 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
反对一下以上几位类似非神人的发言......

若在1个class内

private string str = "You are a joker!";

public void Test()
{
     Func1(str); // str == "You are a joker!" equals true
     Func2(str); // str == "You are a joker!" equals false, str == null equals true!
}

public void Func1(string s)
{
    s = null; // 这里只把s指向了null, str并没有指向null, 因为只是copy了str的value, 即copy a reference-type object, s和str本身的地址并不同
}

public void Func2(ref string s)
{
    s = null; // 这里把s和str同时指向了null, 因为这里s其实是str的 Alias了,即s和str本身的地址亦相同了
}

[ 本帖最后由 自由的心 于 2012-1-11 20:51 编辑 ]

发表于 2012-1-11 19:57 |显示全部楼层

回复 自由的心 50# 帖子

此文章由 hornsay 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 hornsay 所有!转贴必须注明作者、出处和本声明,并保持内容完整
你这个例子想要表达什么?

当你在func2里pass s as reference, 任何改变都会影响到str, 这是基本常识。after calling Func2, joker is gone.  (paopaobing(3))
Advertisement
Advertisement
头像被屏蔽

禁止访问

发表于 2012-1-11 20:00 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
但Func1里,任何改变s都不会影响到str,这也是基本常识,您们为什么似乎不能认同呢?
头像被屏蔽

禁止访问

发表于 2012-1-11 20:15 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
再举个更好的例子

在1个class里

public void Test()
{
    C c = new C() // C is a class, therefore c is a reference-type object / instance
    c.Name = "aaa"; // set c's public property 'Name'

    Func1(c); // c并没有指向null
    Func2(c); // c指向null
}

public void Func1(C c_param)
{
    c_param.Name = "bbb"; // 这里同时改变了c_param和c的Name
    c_param = null; // 这里仅仅把c_param 指向null
}

public void Func2(ref C c)
{
    c_param.Name = "ccc"; // 这里同时改变了c_param和c的Name
    c_param = null; // 这里同时把c_param和c指向null
}

结论:Oh my God, 太经典了!

[ 本帖最后由 自由的心 于 2012-1-11 21:25 编辑 ]

发表于 2012-1-11 20:20 |显示全部楼层
此文章由 hornsay 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 hornsay 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 自由的心 于 2012-1-11 21:00 发表
但Func1里,任何改变s都不会影响到str,这也是基本常识,您们为什么似乎不能认同呢?


兄弟, 这种练习在大学里不止做了多少遍. 你pass s in Func1, 因为不是as reference, 所以在Func1里任何的改变不会影响str.

但是object不一样.

我前面已经讲了, string, integer, float 和object是有区别的. object你哪怕pass not as reference, any change in Func1 will affect 这个object.

Have a try
Func1(MyObject myobject)
{
}

Func2(ref MyObject myobject)
{
}

See any difference?

评分

参与人数 1积分 +1 收起 理由
自由的心 + 1 string s是reference-type object, 和class .

查看全部评分

持不同股见者...
头像被屏蔽

禁止访问

发表于 2012-1-11 20:22 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
看53楼......

发表于 2012-1-11 20:26 |显示全部楼层

回复 自由的心 53# 帖子

此文章由 hornsay 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 hornsay 所有!转贴必须注明作者、出处和本声明,并保持内容完整
这里 c_param.Name是string, 但它的改变是改变了c_param 这个object, 和你单纯pass一个string是有区别的.
Advertisement
Advertisement

发表于 2012-1-11 20:30 |显示全部楼层
此文章由 skyrocket01 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 skyrocket01 所有!转贴必须注明作者、出处和本声明,并保持内容完整
头像被屏蔽

禁止访问

发表于 2012-1-11 20:37 |显示全部楼层
此文章由 自由的心 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 自由的心 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 hornsay 于 2012-1-11 21:26 发表
这里 c_param.Name是string, 但它的改变是改变了c_param 这个object, 和你单纯pass一个string是有区别的.

string s 和 C c都是reference-type objects, 都不是value-type objects.
对,改变了c_param.Name当然就是改变了c_param本身......

发表于 2012-1-11 20:52 |显示全部楼层
此文章由 hornsay 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 hornsay 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 自由的心 于 2012-1-11 21:37 发表

string s 和 C c都是reference-type objects, 都不是value-type objects.
对,改变了c_param.Name当然就是改变了c_param本身......

在C#出来之前,所有的language(C, C++, Pascal)都是把string, integer,float和object区别开来的,也就是说string不是object, 你不会去new一个string, new 一个integer.

但是现在的C#把所有的东西都归在object里,所以变成string也是属于object, 但它还是有区别的,也就是你不会去new一个string, 所以C#让你confuse了这些东西。
持不同股见者...

发表于 2012-1-11 20:54 |显示全部楼层
此文章由 wil 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 wil 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 自由的心 于 2012-1-11 20:47 发表
反对一下以上几位类似非神人的发言......

若在1个class内

private string str = "You are a joker!";

public void Test()
{
     Func1(str); // str == "You are a joker!" equals true
     Func2(str); // str == "You are a joker!" equals false, str == null equals true!
}

public void Func1(string s)
{
    s = null; // 这里只把s指向了null, str并没有指向null, 因为只是copy了str的value, 即copy a reference-type object, s和str本身的地址并不同
}

public void Func2(ref string s)
{
    s = null; // 这里把s和str同时指向了null, 因为这里s其实是str的 Alias了,即s和str本身的地址亦相同了
}


Func1:真不是你说的那样。。。Func1(string s),这里发生的事是,s是str引用的copy,所以s和str两个引用同时指向了一个string对象,并不是copy了str的value,当s = null时,s重新指向了null,str还是指向原来的string对象,就是这样,另外string虽然是object,但是个immutable对象,也就是一旦创建,永不改变

Func2:这里你好像一直纠结觉得ref可以实际上做到让两个引用地址相同,这个是不可能的,当进入Func2这个方法时,就已经是用的是当前线程里的stack里的一块新的地址了,之后Func2里的临时变量都是在stack上继续累加使用新的地址的,所以s和str的地址不可能相同的,给你一个link看看:
http://www.c-sharpcorner.com/Upl ... sharp_memory2B.aspx

这个图可以看到,x和pValue不在同一地址,像我之前说的,pValue是指向引用x的引用

希望你现在能清楚些,还有不要说什么神人不神人的,编程多了就会有常识了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回忆是红色的天空

发表回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Advertisement
Advertisement
返回顶部