2

我试图了解 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。

我想知道 :

  • 我在扩展方法中说 p = new Program() 到底发生了什么?
4

3 回答 3

5

基本上,它的行为没有this. 扩展方法只会使 API 变得方便——它们不会改变行为。

该参数p未传递ref,因此一旦p = new Program();您创建了一个单独且不相关的实例,该实例将无法返回给调用代码。因此,调用者将看不到您的更改,并且100只会在Prod.

或者更具体地说:

pr.Prod();

等同于

DeclaringType.Prod(pr);

它将(引用)的值加载pr到堆栈上并Prod通过静态调用进行调用;

public static void Prod(this Program p)

此时,p是在堆栈中的位置arg0

p = new Program();

创建一个新对象并分配值over arg0 - 请注意pr(引用)的值不受此影响,arg0引用的单独内存位置也是如此。

p.SeeIt = 100;

通过取消引用将成员分配给对象新对象arg0- 同样,末尾 pr的对象对此一无所知。

于 2012-04-13T05:39:12.443 回答
0

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

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

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

于 2012-04-13T05:41:02.497 回答
0

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

不幸的是,您不能执行使用 ref 此参数的扩展方法。

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

于 2012-04-13T05:45:53.243 回答