ref和在C#出参数,并且可以不被标记为变 [英] ref and out parameters in C# and cannot be marked as variant

查看:163
本文介绍了ref和在C#出参数,并且可以不被标记为变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这句话是什么意思呢?

从这里

ref和out参数
  不能被标记为变体。

ref and out parameters in C# and cannot be marked as variant.

1),这是否意味着下无法做到的。

1) Does it mean that the following can not be done.

public class SomeClass<R, A>: IVariant<R, A>
{
    public virtual R DoSomething( ref A args )
    {
        return null;
    }
}

2),它意味着我不能有以下几种。

2) Or does it mean I cannot have the following.

public delegate R Reader<out R, in A>(A arg, string s);

public static void AssignReadFromPeonMethodToDelegate(ref Reader<object, Peon> pReader)
{
    pReader = ReadFromPeon;
}

static object ReadFromPeon(Peon p, string propertyName)
    {
        return p.GetType().GetField(propertyName).GetValue(p);
    }

static Reader<object, Peon> pReader;

static void Main(string[] args)
    {
        AssignReadFromPeonMethodToDelegate(ref pReader);
        bCanReadWrite = (bool)pReader(peon, "CanReadWrite");

        Console.WriteLine("Press any key to quit...");
        Console.ReadKey();
    }

我试过(2)和它的工作。

I tried (2) and it worked.

推荐答案

出的方式,粗略地说,只出现在输出位置。

"out" means, roughly speaking, "only appears in output positions".

在的意思,粗略地说,只出现在输入位置。

"in" means, roughly speaking, "only appears in input positions".

真实的故事比这更复杂一些,但被选择的关键字,因为大部分时间是这种情况。

The real story is a bit more complicated than that, but the keywords were chosen because most of the time this is the case.

考虑的界面的方法,或由一个代表psented方法重新$ P $

Consider a method of an interface or the method represented by a delegate:

delegate void Foo</*???*/ T>(ref T item);

是否牛逼出现在输入位置?是。调用者可以通过中通项T的值;被叫方可以富读取。因此T不能被标记为OUT。

Does T appear in an input position? Yes. The caller can pass a value of T in via item; the callee Foo can read that. Therefore T cannot be marked "out".

是否牛逼出现在输出位置?是。被叫方可以写一个新的值项,调用者可以再读取。因此T不能被标记中的

Does T appear in an output position? Yes. The callee can write a new value to item, which the caller can then read. Therefore T cannot be marked "in".

因此​​如果T出现在参考的形式参数,T不能被标记为或缩小。

Therefore if T appears in a "ref" formal parameter, T cannot be marked as either in or out.

让我们看看事情如何出问题一些真实的例子。想这是合法的:

Let's look at some real examples of how things go wrong. Suppose this were legal:

delegate void X<out T>(ref T item);
...
X<Dog> x1 = (ref Dog d)=>{ d.Bark(); }
X<Animal> x2 = x1; // covariant;
Animal a = new Cat();
x2(ref a);

那么我的狗猫,我们刚刚作出了一个猫皮。 走出去不能是合法的。

Well dog my cats, we just made a cat bark. "out" cannot be legal.

大约什么?

delegate void X<in T>(ref T item);
...
X<Animal> x1 = (ref Animal a)=>{ a = new Cat(); }
X<Dog> x2 = x1; // contravariant;
Dog d = new Dog();
x2(ref d);

和我们只是把一只猫在只能容纳狗的变量。 T不能,在要么被标记。

And we just put a cat in a variable that can only hold dogs. T cannot be marked "in" either.

什么out参数?

delegate void Foo</*???*/T>(out T item);

?现在,只有T出现在输出位置。它应该是合法的,将T标记为OUT?

? Now T only appears in an output position. Should it be legal to make T marked as "out"?

不幸的是没有。 走出去其实并不比参考幕后不同。之间的out和裁判唯一的区别是,的编译的禁止从输出参数读取之前它是由被叫方指定的,而编译器需要被调用正常返回前分配。有人谁写了这个接口的在C#以外的.NET语言的实现的将能已经初始化之前从项目阅读,因此,它可以作为一个输入。因此,我们禁止标记T作为在这种情况下,出。这是令人遗憾的,但没有什么我们可以做些什么;我们必须服从CLR类型的安全规则。

Unfortunately no. "out" actually is not different than "ref" behind the scenes. The only difference between "out" and "ref" is that the compiler forbids reading from an out parameter before it is assigned by the callee, and that the compiler requires assignment before the callee returns normally. Someone who wrote an implementation of this interface in a .NET language other than C# would be able to read from the item before it was initialized, and therefore it could be used as an input. We therefore forbid marking T as "out" in this case. That's regrettable, but nothing we can do about it; we have to obey the type safety rules of the CLR.

此外,出参数的规则是,它们不能用于输入的它们被写入到的前。没有,他们不能的 的它们将被写入后,用于输入规则。假设我们允许

Furthermore, the rule of "out" parameters is that they cannot be used for input before they are written to. There is no rule that they cannot be used for input after they are written to. Suppose we allowed

delegate void X<out T>(out T item);
class C
{
    Animal a;
    void M()
    {
        X<Dog> x1 = (out Dog d) => 
        { 
             d = null; 
             N(); 
             if (d != null) 
               d.Bark(); 
        };
        x<Animal> x2 = x1; // Suppose this were legal covariance.
        x2(out this.a);
    }
    void N() 
    { 
        if (this.a == null) 
            this.a = new Cat(); 
    }
}

我们再一次取得了猫皮。我们不能支持T是走出去。

Once more we have made a cat bark. We cannot allow T to be "out".

这是非常愚蠢的使用了输入参数以这种方式,但合法的。

It is very foolish to use out parameters for input in this way, but legal.

这篇关于ref和在C#出参数,并且可以不被标记为变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆