参考和出参数问题

时间:2015-05-24 23:41:01

标签: c# out ref

我以为我明白了区别,但现在我不太确定。我已多次阅读技术答案,但我不明白发生了什么。我有这个例子。

class Program
   {
      static void Main()
      {
         int val = 0;

         Example1(val);
         Console.WriteLine(val); // Still 0!

         Example2(ref val);
         Console.WriteLine(val); // Now 2!

         Example3(out val);
         Console.WriteLine(val); // Now 3!
      }

      static void Example1(int value)
         {
             value = 1;
         }

      static void Example2(ref int value)
         {
             value = 2;
         }

      static void Example3(out int value)
         {
           value = 3;
         }
    }

我一直认为默认参数之间的区别在于,如果我将val传递给Example1,我就不能使用赋值。

但是ref关键字val仍然是0,但我创建了一个引用,现在被视为Example2(ref val)中的变量“value”。到目前为止,我是否被挂了?如果我用过

int value = 0;
Example1(value);
Console.WriteLine(value); // this would then return 1 correct?

现在,out关键字会发生什么?和ref一样吗?

3 个答案:

答案 0 :(得分:0)

在第一个示例中,您没有指定变量是引用,并且因为它是基本类型,所以它只复制提供的数字。因此value中的Example1valueMain的副本。

第二个示例使用引用。这意味着函数Example2和内部Main内部都指向内存中的相同位置,因此当进入和退出函数时,值都会被转移。

在第三个示例中,out关键字与第二个关键字相同,只是在输入函数时初始化为0。因此,它只是返回某种数据的参数。退出函数时只传输该值。

答案 1 :(得分:0)

看看这是否有帮助:

否"装饰者"

static void Example(int value)
{
    Console.WriteLine("Value is {0}", value);
    value = 99;
}

usage
{
    int value = 10;
    Example(notADefaultValue); // Will print <Value is 10>
    Console.WriteLine("Value is {0}", value); // will print <Value is 10>
}

总结:默认情况下,值类型(结构/枚举/ int / double / etc)不作为引用传入,因此无论您对方法中的变量执行什么操作都不会影响调用方。因此,&#34; ref&#34;关键词。如果将引用类型传递给方法(即类)并更改它的内部,则会影响调用者。

默认参数:

static void Example(int value = 5)
{
    Console.WriteLine("Value is {0}", value);
}

usage
{
    int notADefaultValue = 10;
    Example(notADefaultValue); // Will print <Value is 10>
    Example(); // will print <Value is 5>
}

摘要:默认值允许您在不明确需要传递参数的情况下调用方法,使用默认值。

参考参数:

static void Example(ref int value)
{
    Console.WriteLine("Value is {0}", value);
    value = 99;
}

usage
{
    int value = 10;
    Example(ref value); // Will print <Value is 10>
    Console.WriteLine("Value is {0}", value); // Will print <Value is 99>
}

摘要:如果将值类型作为ref(引用)传递,则值本身会发生更改。默认情况下,所有引用类型都作为ref传入。 FYI,int是一种原始类型,因此需要一个明确的&#34; ref&#34;。

输出参数:

static void Example(out int value)
{
    value = 99;
    Console.WriteLine("Value is {0}", value);
}

usage
{
    int value; // no need to init it
    Example(out value); // Will print <Value is 99>
    Console.WriteLine("Value is {0}", value); // Will print <Value is 99>
}

总结:Out参数类似于返回变量,但是通过方法的签名传入。最常见的示例是TryParse,其中该方法返回重要信息,并且根据该信息,out参数有效或无效(如果为真,则有效)。

答案 2 :(得分:0)

好的,它是评论中链接问题的副本,但我会尝试为您解释。

未修改的参数

案例A:public void MyFunc(int x) { }

- 或 -

案例B:public void MyFunc(MyClass y) { }

在案例A中,参数是值类型,默认情况下,值类型作为原始值的副本传递给函数。这并不意味着您不允许修改该值,但该值不会反映在调用位置。这对于所有值类型都是相同的,在传递给函数之前,值是复制

在案例B中,参数是引用类型。默认情况下会按原样传递这些类型。它们不会被复制,但您不能更改引用(通过为类型指定newnull值)。您可以更改对象的内容(其中的任何属性/字段),反映回调用位置。

ref关键字

案例A:public void MyFunc(ref int x) { }

-OR -

案例B:public void MyFunc(ref MyClass x) { }

在A的情况下,您告诉编译器您希望通过引用传递值,这意味着编译器不会复制该类型,而是传递对该类型的引用。该功能可以更改它。

在案例B中,您告诉编译器允许函数 更改引用指向的位置(您可以创建new或将其设置为null它将反映在呼叫站点中。

out关键字

案例A:public void MyFunc(out int x) { }

-OR -

案例B:public void MyFunc(out MyClass x) { }

在这里,您基本上是为函数定义其他返回类型。它的方法参数告诉调用者在x变量的位置预期结果。两者都是一样的。在任何情况下,调用者都不应该期望之前x之前的任何值都是相同的。实际上,您可以预期它将不相同,因为该方法需要在允许返回之前为x分配新值

out基本上意味着您为返回值提供了一个位置,对于值类型,只需使用默认构造函数,对于引用类型,在将值传递给null之前将其初始化为 getAyahsByJuz: function (juzIndex) { var response = []; var promises = []; var self = this; var deferred = $q.defer(); $timeout(function () { $http.get('data/quran.json').success(function (data) { var ayahs = Quran.ayah.listFromJuz(juzIndex); angular.forEach(ayahs, function (value, key) { var promise = self.getVerse(value.surah, value.ayah).then(function (res) { var verse = { surah: value.surah, ayah: value.ayah, text: res }; response.push(verse); }, function (err) { console.log(err); }); promises.push(promise); }); }); }, 30); $q.all(promises).then(function() { deferred.resolve(response); }); return deferred.promise; },