将扩展方法的行为与方法中的新对象创建混淆
本文关键字:方法 对象 创建 扩展 新对象 | 更新日期: 2023-09-27 18:31:03
我试图理解 c# 扩展方法的行为,发现如下:
下面是类程序的扩展方法,其中有一个名为 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);
我看到下面的东西:
- 当我在扩展方法中评论#@2行时,结果来自扩展方法,即100。
- 当我保持行 #@2 行时,结果是 200。
我想知道:
- 我说 p = 扩展方法中的新程序()到底发生了什么?
基本上,它的行为与没有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();
创建一个新对象并在arg0
上分配值 - 请注意,pr
(引用)的值不受此影响,因为arg0
是引用的单独内存位置。
p.SeeIt = 100;
通过取消引用arg0
将成员分配给对象新对象 - 同样,pr
末尾的对象对此一无所知。
它正在创建Program
的新实例,并且您正在更新该实例的 SeeIt
属性。
a) 当 #@2 被注释时,您正在更新程序原始实例的值,因此设置了属性 100
b) 创建新实例时,旧实例不受影响,属性值不受影响
您正在将 p 的引用替换为另一个实例,这不会影响您传递给扩展方法的引用。我认为您要做的是使参数 p 成为 ref 参数,在这种情况下,传递给方法的内容与方法本身中使用的引用将是相同的。
不幸的是,您无法执行采用 ref 此参数的扩展方法。
请记住,引用基本上是指向实际类实例的指针。