将引用类型和值类型作为参数传递给方法之间的区别

本文关键字:方法 之间 区别 参数传递 引用类型 类型 | 更新日期: 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 TypeValue Type,还有Mutable TypeImmutable 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# 中,发送到方法的所有参数都按值传递,除非它们使用 refout 关键字传递。

这包括值类型、引用类型、可变和不可变类型的参数。

将引用类型参数传递给方法时,实际发生的是参数的引用按值传递。

这意味着该方法实际上包含对传递给它的参数的新引用
因此,当使用方法外部的引用时,对该参数状态的任何更改也将反映。
但是,将新值分配给方法内部的引用时,它不会反映在方法外部的引用上。

有关更好、更广泛的解释,请阅读 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);
}

你可以在这把小提琴上亲眼看到。