与C#和VB如何处理命名的参数差异? [英] Differences between how C# and VB handle named parameters?

查看:163
本文介绍了与C#和VB如何处理命名的参数差异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在名为参数C#支持,我被检查,看它是否实施同样的方式VB做了,而且发现有细微的差别。举个例子像这样的库函数:

 公共静态无效美孚(字符串,字符串二)
{
    Console.WriteLine(的String.Format(一:{0},B:{1},A,B));
}
 


在C#中,如果你把它是这样的:

 美孚(A:A,B:B);
 

编译器生成以下IL指令:

  .locals的init(
    [0]字符串CS $ 0 $ 0000
    [1]字符串CS $ 0 $ 0001)
L_0000:NOP
L_0001:ldstr一个
L_0006:stloc.0
L_0007:ldstrb的
L_000c:stloc.1
L_000d:ldloc.0
L_000e:ldloc.1
L_000f:拨打无效[TestLibrary] TestLibrary.Test ::美孚(字符串,字符串)
L_0014:NOP
L_0015:RET
 

这相当于下面的C#code:

 字符串CS $ 0 $ 0000 =A;
字符串CS $ 0 $ 0001 =B;
Test.Foo(CS $ 0 $ 0000 CS $ 0 $ 0001);
 


在VB中,如果你把它是这样的:

 美孚(A:=A,B:=B)
 

编译器生成以下IL指令:

  L_0000:NOP
L_0001:ldstr一个
L_0006:ldstrb的
L_000b:拨打无效[TestLibrary] TestLibrary.Test ::美孚(字符串,字符串)
L_0010:NOP
L_0011:NOP
L_0012:RET
 

这相当于下面的VB code:

 美孚(A,B);
 


的方式VB做它需要少得多的指令调用,所以它有什么优势的方式C#实现它?如果不使用命名参数,C#产生同样的事情,VB。


修改:现在我们已经确定了额外的指令在释放模式走,是有他们是present在调试模式下一个特别的原因? VB的作用在这两种模式是相同的,并且通常调用该方法时不带命名参数(包括您在使用可选参数)C#不插入额外的指令。

解决方案
  

在那里他们将present在调试模式特别的理由?

不同的是间

  • 在推一个临时的值在栈上,使用它,抛弃它,和
  • 存储临时值到一个特定的栈槽,使得它的副本压入堆栈,使用它,放弃它,但临时值原​​件留在栈槽

此差的可见效果是,垃圾收集器,不能作为积极地清理值。在第一种情况下,该值可以立即收集一次调用返回。在第二个方案中,该值被在当前方法返回后仅收集(或重新使用的时隙)。

使垃圾收集不太积极通常有助于调试方案。

隐含的问题是:

  

为什么C#和VB之间的区别?

在C#和VB编译器被写了谁做他们各自的code发电机的工作原理不同的选择,不同的人。

更新:回复:您的评论

在C#编译器,未优化的IL代基本上是相同的结构特征我们内部重新presentation。当我们看到一个名为参数:

  M(Y:Q(),X,R());
 

所在的方法是,说

 无效M(INT X,int y)对{}
 

我们重新present这在内部,就像你写

  INT ytemp = Q();
INT xtemp = R();
M(xtemp,ytemp);
 

由于我们想preserve的Q和R的副作用左到右评价这是一个合理的内部重新presentation,当我们codeGEN它非优化模式,我们只是$ C CGEN的$ C $ $ C直接从内部重新presentation几乎没有任何改动。

当我们运行优化,我们发现各种东西 - 比如,没有人使用这些看不见的局部变量的任何东西的事实。然后,我们可以从codeGEN消除当地人。

我还不是很了解VB的内部重新presentation;自1995年以来我一直没有工作的VB编译器,我听说它可能稍稍在过去的十五年改变了。我猜想,他们做同样的事情,但我不知道他们是如何重新present命名参数还是怎么的code生成处理它们的细节。

我的观点是,这种差异并没有,据我所知,说明了一个重要的语义差别。相反,它说明了非优化编译刚刚吐出来的,我们碰巧产生,我们知道有所需的语义无论高层内部重新presentation。

Now that C# supports named parameters, I was checking to see if it was implemented the same way VB did it, and found that there is a slight difference. Take for example a library function like this:

public static void Foo(string a, string b)
{
    Console.WriteLine(string.Format("a: {0}, b: {1}", a, b));
}


In C#, if you call it like this:

Foo(a: "a", b: "b");

The compiler produces the following IL instructions:

.locals init (
    [0] string CS$0$0000,
    [1] string CS$0$0001)
L_0000: nop 
L_0001: ldstr "a"
L_0006: stloc.0 
L_0007: ldstr "b"
L_000c: stloc.1 
L_000d: ldloc.0 
L_000e: ldloc.1 
L_000f: call void [TestLibrary]TestLibrary.Test::Foo(string, string)
L_0014: nop 
L_0015: ret 

Which translates to the following C# code:

string CS$0$0000 = "a";
string CS$0$0001 = "b";
Test.Foo(CS$0$0000, CS$0$0001);


In VB, if you call it like this:

Foo(a:="a", b:="b")

The compiler produces the following IL instructions:

L_0000: nop 
L_0001: ldstr "a"
L_0006: ldstr "b"
L_000b: call void [TestLibrary]TestLibrary.Test::Foo(string, string)
L_0010: nop 
L_0011: nop 
L_0012: ret 

Which translates to the following VB code:

Foo("a", "b");


The way VB does it requires much fewer instruction calls, so is there any advantage to the way C# implements it? If you don't use the named parameters, C# produces the same thing as VB.


EDIT: Now that we've determined that the extra instructions go away in release mode, is there a particular reason for them to be present in debug mode? VB acts the same in both modes, and C# doesn't insert the extra instructions when calling the method normally without named parameters (including when you use optional parameters).

解决方案

is there a particular reason for them to be present in debug mode?

The difference is between:

  • push a temporary value on the stack, use it, discard it, and
  • store a temporary value into a specific stack slot, make a copy of it onto the stack, use it, discard it, but the original copy of the temporary value stays in the stack slot

The visible effect of this difference is that the garbage collector cannot be as aggressive about cleaning up the value. In the first scenario, the value could be collected immediately once the call returns. In the second scenario, the value is only collected after the current method returns (or the slot is re-used).

Making the garbage collector less aggressive often helps in debug scenarios.

The implied question is:

Why the difference between C# and VB?

The C# and VB compilers were written by different people who made different choices about how their respective code generators work.

UPDATE: Re: your comment

In the C# compiler, the unoptimized IL generation is essentially of the same structure as our internal representation of the feature. When we see a named argument:

M(y : Q(), x : R());

where the method is, say

void M(int x, int y) { }

we represent this internally as though you'd written

int ytemp = Q();
int xtemp = R();
M(xtemp, ytemp);

Because we want to preserve the left-to-right evaluation of the side effects of Q and R. This is a reasonable internal representation, and when we codegen it in non-optimized mode, we just codegen the code directly from the internal representation with hardly any modifications.

When we run the optimizer we detect all kinds of stuff -- such as the fact that no one uses those invisible local variables for anything. We can then eliminate the locals from the codegen.

I know very little about the VB internal representation; I haven't worked on the VB compiler since 1995, and I hear that it might have changed just slightly in the last fifteen years. I would imagine that they do something similar, but I don't know the details of how they represent named parameters or how their code generator deals with them.

My point is that this difference does not, to my knowledge, illustrate an important semantic difference. Rather, it illustrates that the nonoptimized build just spits out whatever high-level internal representation we happened to generate that we know has the desired semantics.

这篇关于与C#和VB如何处理命名的参数差异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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