C#扩展方法会影响当前实例还是返回相同类型的新对象?

C#扩展方法会影响当前实例还是返回相同类型的新对象?,c#,.net,extension-methods,C#,.net,Extension Methods,使用扩展方法扩展非静态类型时,对“this”执行的工作是发生在扩展类的原始实例上,还是返回应用了这些更改的新实例?或者,根据扩展方法的编写方式,它是否可以这样做 考虑以下示例扩展方法: public static AddressEntity FromAddressLight(this AddressEntity addressEntity, AddressLight addressLight) { if (addressLight == null) { retur

使用扩展方法扩展非静态类型时,对“this”执行的工作是发生在扩展类的原始实例上,还是返回应用了这些更改的新实例?或者,根据扩展方法的编写方式,它是否可以这样做

考虑以下示例扩展方法:

public static AddressEntity FromAddressLight(this AddressEntity addressEntity, AddressLight addressLight)
{
    if (addressLight == null)
    {
        return null;
    }

    var result = new AddressEntity
    {
        Id = addressLight.AddressId,
        AddressName = addressLight.AddressName,
        // other mapping conversions here
    };

    return result;
}
以下哪种调用方法有效

AddressLight light = new AddressLight(); // assume constructor populates this
AddressEntity myEntity = new AddressEntity(); // this constructor does not populate anything

myEntity.FromAddressLight(light); // Will this cause myEntity take on the value of "result" in the extension method?...
myEntity = myEntity.FromAddressLight(light); // ... or is this needed to copy "result" into myEntity?

// ... and why is this not something Visual Studio allows? Does this not become a static member of the extended class?
myEntity = AddressEntity.FromAddressLight(light);

快速回答。。。视情况而定

您给出的示例返回了
AddressEntity
的一个新实例,但没有理由不能返回便于链接的相同实例或完全不同的实例

这取决于你

myEntity=myEntity.FromAddressLight(灯光)
是此方法在示例中的正确用法


myEntity=AddressEntity.FromAddressLight(light)不起作用,因为您调用的是静态方法,而不是实例方法,尽管这有点违反了静态声明的直观性。

这作为扩展方法有点奇怪(作为“普通”静态方法更有意义),但下面按行顺序(跳过前两行):

  • 这没有用。extension方法返回一个新对象,该对象未分配给任何对象,因此超出范围并被垃圾收集

  • 这将完全符合您的想法,并且是使用此方法的唯一“合理”方式

  • 这是不允许的,因为没有传递给函数的“AddressEntity”实例。不是显式地(显然只传递1个参数)或隐式地(因为您使用了类型来访问它,而不是对象)

  • 特别是因为您正在尝试执行(3),所以我不会将此函数作为扩展方法(它甚至不使用任何AddressEntity字段,所以为什么它采用该类型?),而是将其作为一个普通的静态方法

    要明确回答您的问题(标题中):


    扩展方法没有什么特别之处,它只有一个隐式参数(“this”参数),所以调用它时看起来很不错。如果它返回一个新值,您将得到一个新值。如果修改“this”参数,它将修改现有值。实际上,这两种方法都可以做到,没有问题。它完全取决于扩展方法的内容。

    一般来说,这是一种非常奇怪的扩展方法。考虑到扩展方法只是语法糖(如之前所提到的),正常用户会真正期望发生两件事之一:

  • 我调用了扩展方法,得到了我自己的修改版本
  • 我调用扩展方法并得到一个转换后的类型
  • 我认为第二点是你真正想要的:

    public static AddressEntity ToAddressEntity(this AddressLight obj)
    {
        return new AddressEntity
        {
            Id = obj.AddressId,
            AddressName = obj.AddressName,
            // other mapping conversions here
        };
    }
    

    请记住,扩展方法不是基于返回类型,而是基于
    this
    之后指定的类型。因此,在本例中,您只需执行
    AddressEntity addEntity=SomeAddressLight.ToAddressEssentity()。这也是您在任何BCL中都看不到模式
    FromSomething()
    的原因,因为在扩展方法的情况下,它感觉非常违反直觉。

    obj.ext(arg)只是ext(obj,arg)的语法糖,仅此而已。
    AddressEntity.FromAddressLight(light)-此AddressEntity AddressEntity的值是多少?@Hans:差不多。对于:
    NamespaceIUsed.classnamethatthavetoremember.ext(obj,arg)
    来说,这是语法上的甜点。编译器应该明确地将这些名称放入调试中:)注意,VB.NET确实允许
    this
    参数为
    ref
    ,因此,如果你使用VB.NET,你可以允许你的
    ByRef addessEntity
    在返回它之前用say
    addressEntity=result
    进行更改。注意3:它将是(并且已经是)找到它的类的静态方法,而不是
    这个
    参数的类型。这里的每个答案都非常有用。我特别检查了这一点,认为它是正确的,因为它让我找到了“aha”时刻(或者可能是“duh”时刻),您可以在方法内部引用“this”,以便对调用实例进行操作,而不是返回新实例。这是我的具体问题。然而,所有的设计讨论都非常有助于我找到解决方案。事实上,这就是我最后写的东西。一个项目中更高级的人指示我1)使用扩展方法进行类型映射)2)从AddressLight转换为AddressEntity,使用AddressEntity作为“this”。根据这些规定,我创建了奇怪的“FromSomething”扩展方法。事实证明,方向不清楚,并且使用AddressLight作为“this”从AddressLight转换为AddressEntity。虽然这个答案并不适用于我的确切问题,但它是对线程的一个非常有用的补充。