C# ';输出';C中的修饰语#

C# ';输出';C中的修饰语#,c#,out,C#,Out,可能重复: 我不熟悉C#和学习修饰语。我偶然发现 我知道out在这里对于int原语变量很有用,但是对于字符串变量,即使没有out修饰符,引用也会传递给被调用的方法,对吗 即使没有out修饰符,引用也会传递给被调用的方法,对吗 是,但是如果没有out,它们将不会被传回: void M(string s1, out string s2) { s1 = "one"; s2 = "two"; } void Main() { string s = "hello", t = "w

可能重复:

我不熟悉C#和学习修饰语。我偶然发现

我知道
out
在这里对于int原语变量很有用,但是对于字符串变量,即使没有
out
修饰符,引用也会传递给被调用的方法,对吗

即使没有
out
修饰符,引用也会传递给被调用的方法,对吗

是,但是如果没有
out
,它们将不会被传回:

void M(string s1, out string s2)
{
    s1 = "one";
    s2 = "two";
}

void Main()
{
    string s = "hello", t = "world";
    // s = "hello"
    // t = "world"
    M(s, out t);
    // s = "hello"
    // t = "two"
}

字符串
设计为不可变。您可能正在考虑可变引用类型:

class Person { public string Name { get; set; } }

void Main()
{
    var p = new Person { Name = "Homer" };
    // p != null
    // p.Name = "Homer"
    M2(p);
    // p != null
    // p.Name = "Bart"
}

void M2(Person q)
{
    q.Name = "Bart";   // q references same object as p
    q = null;          // no effect, q is a copy of p
}

在从方法返回之前,要求您进行设置。因此,传入什么并不重要,因为它保证会被覆盖

虽然作为输出参数传递的变量在传递之前不必初始化,但在方法返回之前,需要调用的方法分配一个值

但是对于字符串变量,即使没有out修饰符,引用也会传递给被调用的方法,对吗

是的,但是您不能更改引用本身。当您设置
s1=“我已返回”时
在方法内部,您正在为s1变量分配一个新的字符串实例。变量本身是通过值传递的,因此调用函数看不到此赋值

如果您有一个类,这一点会更清楚:

class Foo
{
     public string Value { get; set; }
}
如果将其传递到没有ref或out的方法中,在实例传递引用时,仍然可以看到实例内部的更改:

static void Method(Foo foo)
{
    foo.Value = "Bar";
}
使用此功能,您可以调用:

Foo foo = new Foo { Value = "Foo" };
Method(foo);
Console.WriteLine(foo.Value); // Prints Bar
但是,如果将该值设置为其他实例:

static void Method2(Foo foo)
{
    foo = new Foo {Value = "Bar" };
}
这不会出现:

Foo foo = new Foo { Value = "Foo" };
Method2(foo);
Console.WriteLine(foo.Value); // Prints Foo, not Bar!
通过传递ref或out,可以重新分配变量本身:

static void Method3(ref Foo foo)
{
    foo = new Foo {Value = "Bar" };
}


Foo foo = new Foo { Value = "Foo" };
Method3(ref foo); // This will change what foo references now
Console.WriteLine(foo.Value); // Prints Bar again

区别在于:如果它不是
out
,则调用方中的值不会更新

static void Method(string s1, out string s2)
{
    s1 = "I've been returned";
    s2 = "changed!!!";
}

static void Main()
{
    string str1 = "one";
    string str2 "two";
    Method(str1, out str2);
    // str1 is still "one"
    // str2 is "changed!";
}

请注意,您的示例中
str2
null
实际上来自方法。你只是看不到区别,因为在通话前后都是空的。

对于你的主要问题来说,这有点离题,但我认为这可能会帮助你更好地理解
out
修饰符的用途

out
参数的另一个有用模式可以在
Int32.TryParse(字符串值,out int i)
等方法中看到,这些方法允许您编写无需手动处理常见异常的代码,例如

int i;
if (Int32.TryParse("blah", out i))
{
  Console.WriteLine("Valid Integer");
}
else
{
  Console.WriteLine("Invalid input");
}
这是一个简单的例子,但它是一个相当常见和有用的模式,用于尝试并执行一些操作,并返回是否成功以及结果值


另一个在.NET中更广泛使用的例子是字典上的
TryGetValue()
方法-请参阅(MSDN)。

不,不正确。如果字符串参数未标记为out,则s1和s2将被视为局部变量。考虑ref和out,因为您不是使用引用本身,而是使用对引用的引用。对于引用类型(如字符串),引用将按值传递。这意味着您可以更改实例的内容,但不能更改引用本身。对于字符串,您甚至不能更改内容,因为它们是不可变的。+1。我很高兴能想出完全相同的答案:)
int i;
if (Int32.TryParse("blah", out i))
{
  Console.WriteLine("Valid Integer");
}
else
{
  Console.WriteLine("Invalid input");
}