class OutReturnExample
{
static void Method(out int i, out string s1, out string s2)
{
i = 44;
s1 = "I've been returned";
s2 = null;
}
static void Main()
{
int value;
string str1, str2;
Method(out value, out str1, out str2);
// value is now 44
// str1 is now "I've been returned"
// str2 is (still) null;
}
我是C#的新手并且学习了修饰符。我遇到了this snippet on MSDN。
我理解out
对于int原始变量很有用,但对于字符串变量,即使没有out
修饰符,引用也会传递给被调用的方法,对吗?
答案 0 :(得分:9)
即使没有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"
}
string
被设计为不可变的。您可能正在考虑可变引用类型:
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
}
答案 1 :(得分:3)
但对于字符串变量,即使没有out修饰符,引用也会传递给被调用的方法,对吗?
是的,但您无法更改参考本身。在方法内部设置s1 = "I've been returned";
时,您需要为s1变量分配新的字符串实例。变量本身是按值传递的,因此调用函数没有看到这个赋值。
如果你有一个班级,那就更清楚了:
class Foo
{
public string Value { get; set; }
}
如果将此传递给没有引用或退出的方法,您仍然可以看到实例中的更改,因为它传递了引用:
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
答案 2 :(得分:3)
区别在于:如果它不是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!";
}
请注意,示例中null
的{{1}}实际上来自Method。您无法看到差异,因为它在调用之后和之前为空。
答案 3 :(得分:0)
在从方法返回之前,您必需设置out
parameters。所以传入的内容并不重要,因为它可以保证被覆盖。
虽然作为out参数传递的变量在传递之前不必初始化,但是在方法返回之前需要调用方法来赋值。
答案 4 :(得分:0)
对于您的主要问题,这有点偏离主题,但我认为这可能有助于您更好地理解out
修饰符的用途。
out
参数的另一个有用模式可见于Int32.TryParse(String value, out int i)
等方法,它们允许您编写不必手动处理常见异常的代码,例如,
int i;
if (Int32.TryParse("blah", out i))
{
Console.WriteLine("Valid Integer");
}
else
{
Console.WriteLine("Invalid input");
}
这是一个微不足道的例子,但它是一个相当普遍和有用的模式,尝试做一些操作并返回它是否成功和结果值。
.NET中另一个更广泛使用的示例是字典上的TryGetValue()
方法 - 请参阅 Dictionary.TryGetValue Method (TKey, TValue) (MSDN)。