扩展方法如何在引擎盖下工作?

时间:2012-01-10 13:49:52

标签: c# asp.net extension-methods

我工作的承包商正在使用extension methods在我们拥有的众所周知的内部类上实施CRUD。我说由于以下原因,最好使用普通inheritance而不是extension methods

  • 使用扩展方法混淆,隐藏&混淆CRUD方法的来源。
  • 我认为extension methods大量使用reflection(速度较慢)。

他的逻辑是,“这是编译的,所以它很快。”也许我错了......但是因为它被编译并不意味着它不使用反射,也不意味着它比正常继承更快。

所以我的问题是:

  1. extension methods如何在幕后工作?
  2. 在您所拥有的WELL-KNOWN课程中使用inheritanceextension methods会更好吗?

6 个答案:

答案 0 :(得分:19)

  

扩展方法如何在引擎盖下工作?

它们只是静态方法;编译器会将myObject.MyExtensionMethod()之类的调用重写为MyExtensionClass.MyExtensionMethod(myObject)

  

在你所掌握的WELL-KNOWN课程中使用inheretance或extension方法会更好吗?

这个问题没有单一答案,这完全取决于具体情况。但通常扩展方法在这些情况下最有用:

  • 您不拥有扩展类型的代码
  • 该方法以接口为目标,并且对于此接口的所有实现都是相同的(例如IEnumerable<T>和Linq扩展方法)

答案 1 :(得分:12)

  

我认为扩展方法大量使用反射(速度较慢)。

没有。扩展方法在编译时解决,不需要反映 这否定了你的表现问题。

  

使用固有或扩展方法是否更好?

我不会说。使用存储库(DAL)。一个实体应该是持久性不可知的(因此:没有来自执行CRUD的基础的继承)并且不假装涉及它不是(没有扩展)。

你是对的“使用扩展方法混淆和混淆CRUD方法的来源”,但继承不是解决方案。

答案 2 :(得分:2)

描述

Extension Methods是一种语言功能。编译器从中生成常规IL(又名MSILCIL)代码。不需要反思。

更多信息

答案 3 :(得分:1)

您的问题及其现有答案都缺少更大的图景。加入正在进行的项目的新开发人员应该符合现有的编码风格和标准,即使他们不是新人的首选。

如果方法的变化代表了主要的功能改进,而不是主要的美学差异,那么首先应该由整个团队进行讨论和批准。

一旦完成,更改应该是批量实现的,并且样式指南更新为仅包含新方法,或者旧方法应该被标记为已弃用和现代化,因为触及了包含它的代码。在后一种情况下,最好将清理更改与现有功能的添加/删除/修改分开提交,以便保持差异中各个修改的原因。

答案 4 :(得分:1)

回答第一个问题:

在幕后,扩展充当代理,这样void MyExtension(此对象obj)可以重写为Action MyDelegate。但是,它们的区别在于,在调用语法时,因为Action必须环绕对象,而扩展可以被调用,就好像它是对象本身的一个成员一样,即使它在引擎盖下它也不是(也没有)就此而言,可以直接访问对象的私有或受保护成员。

回答第二个问题:

我通常为我不拥有的类或接口保留扩展名。

例如,假设您有一个接口IAnimal

Public Interface IAnimal
{
    void Speak();
    void RunToOwnerWhenCalled();
}

以下课程

public class Mammal
{
    public virtual void AnswerWhatAmI()
    {
        Console.WriteLine("I'm a mammal");
    }
}

public class Dog:Mammal, IAnimal
{
    public void Speak()
    {
        Console.WriteLine("arf");
    }

    public void RunToOwnerWhenCalled()
    {
        Console.WriteLine("Comming");
    }
}

public class Cat:Mammal, IAnimal
{
    public void Speak()
    {
        Console.WriteLine("meow");
    }

    public void RunToOwnerWhenCalled()
    {
        Console.WriteLine("I don't know you");
    }
}

然后你可以有像

这样的扩展名
Public static void CallAnimal(this IAnimal animal)
{
    animal.RunToOwnerWhenCalled();
}

这样的方法
Public static void Main
{
    Cat cat = new Cat();
    cat.CallAnimal();
}

结果将在控制台中显示猫对“我不认识你”的回应。

再考虑一个课程

Public class Human:Mammal
{
    Public Human():base()
    {
        Console.WriteLine("To be more specific, I am a human.");
    }
}

这个类没有CallAnimal扩展名,因为它不会影响IAnimal接口,即使它是一种Mammal类型。

答案 5 :(得分:0)

在引擎盖下,扩展方法就像常规方法一样,它被调用的对象作为第一个参数(this参数)传递。扩展方法没有什么特别之处,它只是语法糖果

尽可能避免使用扩展方法是一种很好的做法。它们使代码的可读性降低,并且不那么面向对象。

如果它是您拥有的类,我认为没有理由为其添加扩展方法。