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";
}