解决方案 »
- C#SerialPort的DataReceived事件
- datalist嵌套的问题
- .net安装部署出现问题
- winform 下.excel..
- 如何获取Tom邮箱注册的验证码
- 请问如何获取指定目录里全部内容所占硬盘存储空间的大小
- 请教高人帮忙!各位大哥帮帮小妹
- 怎样用C#能写GSM手机的操作系统啊? 我想将自己的手机来试验一下。各位感兴趣的和会做的帮忙顶一下!
- C#中什么控件可以实现此类下拉框?
- C#.NET 2003 启动不了测试 报错:无法自动将服务器设置为正确的调试状态。 附加问题:IIS7.0怎么降为IIS6.0。
- 如何获得计算机所在域的列表
- 两层循环取指定行有效数据,取不够行了怎么办?
结构是在栈上分配空间的,类是在栈上分配一个变量指针,使用new后在堆上分配存储工具,所以没有被new的类是null,而结构不会是null
“Java 方法的参数是按什么传递的问题,其答案就只能是:即是按值传递也是按引用传递,只是参照物不同,结果也就不同。”
“Java 中,改变参数的值有两种情况,第一种,使用赋值号“=”直接进行赋值使其改变;第二种,对于某些对象的引用,通过一定途径对其成员数据进行改变。对于第一种情况,其改变不会影响到方法该方法以外的数据,或者直接说源数据。而第二种方法,则相反,会影响到源数据——因为引用指示的对象没有变,对其成员数据进行改变则实质上是改变的该对象。”我可否理解成:
1。类的实例在使用的时候,都是按引用传值?C++, C#, Java都是这样。2。而另外一方面,函数参数传值的时候,C#和Java一样,即是按值传递也是按引用传递,只是参照物不同,结果也就不同。而C++因为还存在指针,所以执行的是另外一套规则?谢谢了。
例如ClassA a=new ClassA();
ClassA otherA=a;
//这里a和otherA都是引用类型,他们引用的都是新建的ClassA对象的地址。
//本质上说,a和otherA的内存空间中,存放的不是创建的对象的内容,而是指向对象内容存放空间的首地址!
而值类型是在stack中分配内存的。
//这里使用的是结构,故不能直接用 items[1].DisplayText = "金星";,如果 Item 是类,则可以直接用。
//为什么呢?因为结构是按值传递的。结构类型是值类型,这是C#编译器的设计,所以不能像类一样用.号引用成员!
{
public int Id;
public string DisplayText;
}Item item1 ;
item1.Id = 0; // 这个地方不是通过. 成员 来赋值的吗
item1.DisplayText = "水星";
Java 1.5的enum类型是值类型的,
其他都是引用类型的。C#的struct可以定义值类型,class定义引用类型,enum定义值类型。就这样~
Java没有结构体,很耗费JVM的heap。
用引用传递值类型可以提高性能
public struct Item
{
public int Id;
public string DisplayText;
}
class Program
{
static void Main(string[] args)
{
List<Item> items = new List<Item>(); //添加
Item item1 = new Item();
item1.Id = 0;
item1.DisplayText = "水星";
items.Add(item1); //添加
Item item2 = new Item();
item2.Id = 1;
item2.DisplayText = "地球";
items.Add(item2); Item item = items[1];
item.DisplayText = "jinxing";
}
}这段代码没问题啊,楼主
不过copy完了后,这个临时的拷贝应该就被销毁了吧
虽然代码没有问题,那是因为你没有测试到“点子”上。如果你打印items[1]的内容,仍然是“地球”而不是“金星”!
结构还可以包含构造函数、常量、字段、方法、属性、索引器、运算符、事件和嵌套类型,但如果同时需要上述几种成员,则应当考虑改为使用类作为类型。
http://msdn.microsoft.com/zh-cn/library/saxz13w4(v=VS.80).aspx
结构与类共享几乎所有相同的语法,但结构比类受到的限制更多: •在结构声明中,除非字段被声明为 const 或 static,否则无法初始化。•结构不能声明默认构造函数(没有参数的构造函数)或析构函数。结构的副本由编译器自动创建和销毁,因此不需要使用默认构造函数和析构函数。实际上,编译器通过为所有字段赋予默认值(参见默认值表)来实现默认构造函数。结构不能从类或其他结构继承。结构是值类型 -- 如果从结构创建一个对象并将该对象赋给某个变量,变量则包含结构的全部值。复制包含结构的变量时,将复制所有数据,对新副本所做的任何修改都不会改变旧副本的数据。由于结构不使用引用,因此结构没有标识 -- 具有相同数据的两个值类型实例是无法区分的。C# 中的所有值类型本质上都继承自 ValueType,后者继承自 Object。结构设计请注意这个例子,MSDN的这个例子和楼主要的完全吻合。
如何:了解向方法传递结构和向方法传递类引用之间的区别(C# 编程指南)
public T get_Item(int index)
{
if (index >= this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
return this._items[index];
}
是什么意思?
return this._items[index];
this._items[index]已经是一个副本了。所以你通过List[i]访问的,就是副本,无法修改。
首先要明白什么叫做按值、按引用传递?这里去重复c语言规则就会出笑话了。当你在调用方法的参数上,假设传递的是对象,不写ref就是按值传递对象吗?写ref就是按引用传递对象吗?如果你这样理解就完全把c的概念张冠李戴到c#上了。这样,也就无法进一步理解值类型的数据的传递。
再说明白一点this._items[index],这个是的的确确你添加进去的那个结构体,但结构体是传值的,在函数调用 void Foo(StructValue o)
这里,你的o是传递的值,那么换一种写法
StructValue Foo()
{
StructValue f;
return f;//你认为这里返回的是f还是f的副本呢?想明白这个,结合List索引器的get代码,应该明白原因了,不要纠结了,换用类吧。
}
非常贴切,但未必能理解。我举个例子描述一下sp1234大神的意思。
public class A
{
public int i = 0;
}A obj = new A();
public void Foo(obj);public void Foo(A a)
{
a.i = 5;//你可以修改a的i属性,因为a是传递的引用。但写不写ref可不同哦。
a = new A();//你可以给a重新赋值,但是a是传进来参数的副本,a的修改不过是形参,obj.i已然是5,不是0
}A obj = new A();
public void Foo(ref obj);public void Foo(ref A b)
{
b.i = 6;//b作为引用,修改i的值为6
b = new A();//你可以修改b的值,离开方法后,参数就变了,obj.i就是0了。
}
按引用传递值类型(如本主题前面所示)是有用的,但是 ref 对于传递引用类型也是很有用的。这允许被调用的方法修改该引用所引用的对象,因为引用本身是按引用来传递的。下面的示例显示出当引用类型作为 ref 参数传递时,可以更改对象本身。
{
//定义一个泛型List
List<AA> datas = new List<AA>();
//添加2个元素,value分别为1,2
datas.Add(new AA(1));
datas.Add(new AA(2));
//打印出当前元素
Console.WriteLine("原始List:");
datas.ForEach(o => Console.WriteLine(o.value.ToString()));
//使用List的索引器赋值
datas.ForEach(o => o.value++);
//打印出当前元素
Console.WriteLine("使用List的索引器赋值");
datas.ForEach(o => Console.WriteLine(o.value.ToString()));
//反射List内部的值类型数组赋值
AA[] items = (AA[])((FieldInfo)(datas.GetType().GetMember("_items", BindingFlags.NonPublic | BindingFlags.Instance)[0])).GetValue(datas);
items[0].value++;
items[1].value++;
//打印出当前元素
Console.WriteLine("反射List内部的值类型数组赋值");
datas.ForEach(o => Console.WriteLine(o.value.ToString()));
}结果原始List:
1
2
使用List的索引器赋值
1
2
反射List内部的值类型数组赋值
2
3还没看懂的,最后再讲一次。
List<T>[i]
这是叫做索引器的,索引器是一种属性,属性就是在调用方法,而值类型无法返回一个引用,返回的是值,所以索引器返回的,是你添加进去变量的副本。而因为值类型无法传递引用,所以添加实际也是使用副本的方式添加的。所以对于值类型的List<T>,索引器的结果,可以访问,可以修改,但无法直接存回去,如何保存?可以重新的赋值,例如
List<Point> points = new List<Point>();
points.Add(new Point());//0,0
修改呢,就整个重新复制
points[0] = new Point(1,1);
你不能修改一项points[0].X = 1;
这样不可以的。希望这样说,各位不明白的能明白。明白的更明白。
{
public int value;
public AA(int v)
{
value = v;
}
}
类是引用类型但是结构也可以用引用方式传递
用关键字 ref