将引用类型和值类型作为参数传递给方法之间的区别
本文关键字:方法 之间 区别 参数传递 引用类型 类型 | 更新日期: 2023-09-27 17:56:37
只是让我一整天都在脑海中运行这种混乱。我在传递给方法的引用和值类型之间非常困惑。
假设我有 2 个类 A 类和 B 类,分别对应于引用和值类型。
public Class A
{
public static void main(string[] args)
{
String s = “hello”;
String w = Changestring(s);
String x = s;
}
private string Changestring(string s)
{
s += “Hi”;
return s;
}
}
.
public Class B
{
public static void main(string[] args)
{
int s = 99;
int w = Changeint(s);
int x = s;
}
private int Changeint(int s)
{
s += 30;
return s;
}
}
我在将引用类型(字符串)和值类型(int)作为参数传递给函数之间感到困惑。 当我运行这样的程序时,字符串(引用类型)的 x 本身是"hello",值类型的 x 是 99。x 应该是"HelloHi"而不是"hello",因为它是引用类型吗?
请帮助我清除这个简单的疑问。
除了Reference Type
和Value Type
,还有Mutable Type
和Immutable Type
。
Immutable
表示对象在初始化后不能也不会更改。因此,您的语句只会生成新字符串,而不会修改原始字符串。
s += "嗨";
字符串对象hello
保持hello
。变化是s
被分配了一个新对象helloHi
。
以
string
为例,您很不幸。
尝试在示例中使用可变类型,例如 StringBuilder
。
public class C
{
public static void Main(string[] args)
{
StringBuilder s = new StringBuilder("hello");
StringBuilder w = Changestring(s);
StringBuilder x = s;
}
private static StringBuilder Changestring(StringBuilder s)
{
s.Append("Hi");
return s;
}
}
要知道,按值传递不会更改初始变量值,其中按引用传递也会更改方法引用的初始变量值。
默认情况下int
被视为值类型,因此它是按值传递的。但是,即使将String
声明为类(引用类型),默认情况下它使用修饰符是不可变的sealed
因此被视为按值传递并添加新字符只是创建String
的新实例,而不是更改当前实例。
通过添加ref
关键字,您可以将 int 行为更改为按引用传递:
public Class B
{
public static void main(string[] args)
{
int s = 99;
int w = Changeint(s); // w has changed
int x = s; // s has also changed
}
private int Changeint(ref int s)
{
s += 30; // result = 129
return s;
}
}
对于类 A,您需要一个 StringBuilder 实例来完成"helloHi":
public Class A
{
public static void main(string[] args)
{
String s = “hello”;
String w = Changestring(s);
String x = w; // if you assign s to x, you will just get "hello"
}
private string Changestring(string s)
{
StringBuilder sb = new StringBuilder();
sb.Append(s);
sb.Append(“Hi”);
return sb.ToString(); // "helloHi"
}
}
中医网.
在 c# 中,发送到方法的所有参数都按值传递,除非它们使用 ref
或 out
关键字传递。
这包括值类型、引用类型、可变和不可变类型的参数。
将引用类型参数传递给方法时,实际发生的是参数的引用按值传递。
这意味着该方法实际上包含对传递给它的参数的新引用。
因此,当使用方法外部的引用时,对该参数状态的任何更改也将反映。
但是,将新值分配给方法内部的引用时,它不会反映在方法外部的引用上。
有关更好、更广泛的解释,请阅读 Jon Skeet 的 C# 中的参数传递一文。
不能使用任何不可变类型对此进行测试,因为根据定义,不可变类型无法更改。
但是,您可以使用任何可变类型对此进行测试:
public static void Main()
{
var x = new List<int>();
x.Add(1);
Add(x, 2);
Console.WriteLine(x.Count.ToString()); // will print "2";
AddRef(ref x, 3);
Console.WriteLine(x.Count.ToString()); // will print "1";
Add3(x, 1, 2, 3 );
Console.WriteLine(x.Count.ToString()); // will also print "1";
Add3Ref(ref x, 1, 2, 3 );
Console.WriteLine(x.Count.ToString()); // will print "3";
}
static void Add(List<int> list, int value)
{
// adding an item to the list, thus chaning the state of the list.
// this will reflect on the list sent to the method,
// since a List is a reference type.
list.Add(value);
}
static void AddRef(ref List<int> list, int value)
{
list = new List<int>(); // same as the s += “Hi”; in the question
// Adding the value to the list.
// Note that this change will reflect on the list passed to the method,
// since it is passed using the ref keyword.
list.Add(value);
}
static void Add3(List<int> list, int value1, int value2, int value3)
{
list = new List<int>(); // same as the s += “Hi”; in the question
// these values are added to the new list.
// since the reference to the list was passed by value,
// it WILL NOT effect the list sent to the method.
list.Add(value1);
list.Add(value2);
list.Add(value3);
}
static void Add3Ref(ref List<int> list, int value1, int value2, int value3)
{
list = new List<int>(); // same as the s += “Hi”; in the question
// these values are added to the new list.
// since the list was passed by reference,
// it WILL effect the list sent to the method.
list.Add(value1);
list.Add(value2);
list.Add(value3);
}
你可以在这把小提琴上亲眼看到。