我开始学习C#并且可以使用以下结果向我解释有关值类型和引用类型的信息。我的理解是整数和结构是值类型因此因此被复制到赋值中,字符串和类是引用类型,因此只复制引用而不是底层对象。这是我测试它的代码:
struct MyStruct
{
public class C
{
public string _string;
};
public C _c;
public string _string;
public int _a;
public MyStruct(int a, string s)
{
_a = a;
_c = new C();
_c._string = s;
_string = s;
}
};
public static void Main(string[] args)
{
MyStruct stru = new MyStruct(4, "Hello");
MyStruct stru2 = stru;
stru2._a = 5;
stru2._string = "World";
stru2._c._string = "World";
Console.WriteLine("Stru _a: " + stru._a);
Console.WriteLine("Stru2 _a: " + stru2._a);
Console.WriteLine("Stru _string: " + stru._string);
Console.WriteLine("Stru2 _string: " + stru2._string);
Console.WriteLine("Stru C _string: " + stru._c._string);
Console.WriteLine("Stru2 C _string: " + stru2._c._string);
}
在这个人为的例子中,我得到以下输出:
Stru _a: 4
Stru2 _a: 5
Stru _string: Hello
Stru2 _string: World
Stru C _string: World
Stru2 C _string: World
int变量_a非常有意义。它是一个值类型,因此它被复制而不被引用,因此对“Stru2”的更改不会影响“Stru”。 _string让我感到惊讶,因为它是一个引用类型,我希望这两个值都输出为“World”。我希望_c._string都像它一样是“世界”,但是我不明白为什么行为与_string不同而不是类的一部分。 任何解释将不胜感激。 谢谢!
答案 0 :(得分:1)
我的理解是整数和结构是值类型因此因此被复制到赋值中,字符串和类是引用类型,因此只复制引用而不是底层对象。
这是正确的。但是,通过相同的逻辑,当您复制包含引用类型成员的结构时,将复制其引用值,而不是基础值。因此,当您复制结构时,其所有值都将复制到复制的结构:int 值,字符串引用和C
< em> reference ,因为C
是引用类型。
因此,两个struct副本都包含对同一底层C
对象的引用。因此,如果您改变C
对象,则更改将出现在两个结构中,因为它们都引用同一个对象。
但是对于_string
成员,当您执行stru2._string = "World"
时,替换引用。这会更改stru2
结构,但因为它是stru
的完整副本,所以原始结构不会受到影响。
仅仅因为一种类型是值类型(或引用类型),并不意味着其成员也具有相同的效果。
答案 1 :(得分:1)
struct MyStruct // Value type
{
public class MyClass // Ref type
{
public string myClassString;
};
public MyStruct(int a, string s)
{
myStrucInt = a;
myClass = new MyClass();
myClass.myClassString = s;
myStractString = s;
}
public MyClass myClass;
public string myStractString;
public int myStrucInt;
};
public static void Main(string[] args)
{
MyStruct stru = new MyStruct(4, "Hello"); // val type
MyStruct stru2 = stru; // val type (makes a copy for stru)
stru2.myStrucInt = 5;
stru2.myStractString = "World";
stru2.myClass.myClassString = "World";
Console.WriteLine("Stru _a: " + stru.myStrucInt); // 4
Console.WriteLine("Stru2 _a: " + stru2.myStrucInt); // 5
Console.WriteLine("Stru _string: " + stru.myStractString); // Hello is original value of stru (struct is value type)
Console.WriteLine("Stru2 _string: " + stru2.myStractString); // World
Console.WriteLine("Stru C _string: " + stru.myClass.myClassString); // World
Console.WriteLine("Stru2 C _string: " + stru2.myClass.myClassString); // World
}
答案 2 :(得分:0)
那是因为两个结构共享同一个MyStruct.C
类的实例。你可以像这样测试它
Console.WriteLine(stru._c == stru2._c);
当您创建第二个结构并初始化第一个结构时,第一个结构对MyStruct.C
实例的引用,第一个结构保留了引用,被复制到第二个结构。
我建议您对代码进行以下更改
//stru2._c._string = "World";
stru2._c = new MyStruct.C();
stru2._c._string = "World";
答案 3 :(得分:0)
我认为这是因为字符串是不可变的 获取相同值的任何字符串变量都指向内存中的同一共享位置。 所以当你设置stru2 = stru,stru._string和stru2._string指向同一个地方时,当你设置stru2._string =“World”时,stru2._string指向一个新的地方而不是stru._string。 对于_c,情况有所不同:由于stru._c和stru2._c指向同一个地方,所以stru2._c的任何属性的任何更改都将改变stru._c的任何属性。