c# ref vs out
1. ref vs out
- out 和 ref生成的方法元数据基本没有差别,所以其对于CLR 和 IL没有差别。
- out 和 ref影响的是c#编译器的行为,它会对out和ref代码使用不同的检测规则。
为尺寸较大的值类型使用out,可以提升代码的执行效率,因为避免了在方法调用时复制值类型的一个新实例。
out/ref | 初始化 | 作用域 | 返回 |
---|---|---|---|
out | 在调用函数中无需初始化 | 被调函数中无法访问初始值 | 被调函数返回前必须向out参数写入值 |
ref | 需要初始化 | 读写 | 读写 |
2. ref 和out的作用到底是什么?
在Main函数中定义了一个变量(值类型或引用类型),ref或out参数传递时,传递的是 指向这个变量 栈中地址的一个指针。
- 对值类型,赋值修改,则修改内存桟中的值。
- 对引用类型,赋值一个新对象,则栈中指针指向新的 堆对象。
注意其中的注释和输出
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder("1");
// ================================================================
// 未使用ref时,传递引用参数时,是在 栈中 新建了一个 堆对象 的引用
//test(sb);
//&sb
//0x0617eec4
// sb: 0x02a2116c
//&sb
//0x0617ee74 //栈中的新指针实例
// sb: 0x02a2116c
//&sb
//0x0617ee74
// sb: 0x02a41904
//&sb
//0x0617eec4
// sb: 0x02a2116c
//Console.WriteLine(sb.ToString());
// out: 1
// ================================================================
// 使用ref是,传递引用参数时,传递的是指针的指针,并没有在栈中新建 指向 堆对象 的指针实例
//test(ref sb);
//&sb
//0x0589ed74
// sb: 0x02ba116c
//&sb
//0x0589ed74 //指针的指针
// sb: 0x02ba116c
//&sb
//0x0589ed74
// sb: 0x02bc1904
//&sb
//0x0589ed74
// sb: 0x02bc1904
//Console.WriteLine(sb.ToString());
// out: 2
// ==============================================================
var str = "1";
test(ref str);
Console.WriteLine(str);
// out: 2
Console.Read();
}
static void test(ref StringBuilder sb)
{
sb = new StringBuilder("2");
}
static void test(StringBuilder sb)
{
sb = new StringBuilder("2");
}
static void test(ref string sb)
{
sb = "2";
}
static void test(string sb)
{
sb = "2";
}