在方法中创建新对象时扩展方法的混乱行为

时间:2012-04-13 05:32:22

标签: c# extension-methods

我试图理解c#的扩展方法的行为,并在下面找到了东西:

下面是类Program的扩展方法,它有一个名为SeeIt的字段。

public static void Prod(this Program p)
{
   Console.WriteLine("i am in ext- pro" );
   p = new Program();   // look out for this line (call this line as #@2)
   p.SeeIt = 100;
}

现在我这样称呼这个方法:

var pr = new Program();
pr.SeeIt = 200;

pr.Prod();

COnsole.WriteLine(pr.SeeIt);

我在下面看到的东西:

  1. 当我在扩展方法中评论#@ 2行时,结果来自扩展方法,即100。
  2. 当我保持#2行的行时,结果是200。
  3. 我想知道:

    • 在扩展方法中我说p = new Program()的确是怎么回事?

3 个答案:

答案 0 :(得分:5)

基本上,它的行为完全与没有this时的行为相同。扩展方法只使API变得方便 - 它们不会改变行为。

参数p未通过ref,因此只要您执行p = new Program();,就会创建一个单独且无关的实例,可用回到调用代码。因此,来电者不会看到您的更改,100只会在Prod中显示。

或更具体地说:

pr.Prod();

相同
DeclaringType.Prod(pr);

pr(引用)的值加载到堆栈上,并通过static-call调用Prod;

public static void Prod(this Program p)

此时,p位于堆栈的arg0位置。

p = new Program();

创建一个新对象并将值分配给 arg0 - 请注意pr(引用)的值不受此影响,因为arg0是一个单独的内存位置供参考。

p.SeeIt = 100;

通过解除引用arg0将成员分配给对象新对象 - 再次, pr末尾的对象对此一无所知。

答案 1 :(得分:0)

它正在创建Program的新实例,并且您正在更新该实例的SeeIt属性。

a)注释#@ 2时,您正在更新Program的原始实例的值,因此设置了属性100

b)创建新实例时,旧实例不受影响且属性值不受影响

答案 2 :(得分:0)

您正在将p的引用替换为另一个实例,这不会影响您传递给扩展方法的引用。我认为你要做的是将参数p作为ref参数,在这种情况下,传递给方法和在方法本身中使用的参数之间的引用将是相同的。

不幸的是,您无法使用引用此参数的扩展方法。

请记住,引用基本上是指向实际类实例的指针。