23

我很难理解部分方法的用法。

您能否提供一个与 LINQ 或此类数据库无关的示例?

部分方法是否与我们在 WinForms 中并在其后面编码时相同,如果我们使用一个方法,它会被编译,但如果我们不这样做,那么它会被编译器删除?那是对的吗?

4

3 回答 3

32

当你有一个分部类时,你可以在一个文件中定义方法的签名并在另一个文件中实现。那是部分方法。

所以在一个文件中你有:

partial class Foo
{
    partial void Bar();  // no implementation

    public void DoSomething()
    {
        // do some stuff...
        Bar();    // this will be removed if Bar isn't implemented in another partial class
        // do something else...
    }
}

而在另一个你有

partial class Foo
{
    partial void Bar()
    {
        // do something...
    }
}

这样可以让第一个文件调用Bar而不用担心是否Bar实现。如果Bar未在某处实现,则删除对它的调用(从此处):

部分方法使类的一部分的实现者能够定义方法,类似于事件。类的其他部分的实现者可以决定是否实现该方法。如果方法未实现,则编译器删除方法签名和对该方法的所有调用。对方法的调用,包括调用中的参数评估可能产生的任何结果,在运行时都没有影响。因此,分部类中的任何代码都可以自由使用分部方法,即使没有提供实现。如果方法被调用但未实现,则不会导致编译时或运行时错误。

部分方法必须返回 void,否则如果未实现该方法,则删除所有方法调用是不安全的:

部分方法声明必须以上下文关键字 partial 开头,并且方法必须返回 void。

与部分类一样,主要用途是使用生成的代码:

部分方法作为自定义生成代码的一种方式特别有用。它们允许保留方法名称和签名,以便生成的代码可以调用该方法,但开发人员可以决定是否实现该方法。与分部类非常相似,分部方法使代码生成器创建的代码和人类开发人员创建的代码能够一起工作,而无需运行时成本。

因此,您可能已经生成了调用部分方法的代码(在生成的代码中未实现定义),并且您可以自由扩展该部分类并根据需要/需要实现该部分方法。

于 2016-04-11T20:12:25.913 回答
6

这是我在自己的编程中使用的一个例子……作为一名教师,我经常向我的同学提供代码示例。但是,我希望他们一步一步地实现他们的编码项目,随着时间的推移,它会变得越来越复杂。更具体地说,假设我为他们提供了代码来运行菜单来测试和驱动他们需要实现的类。第 1 步,菜单很简单。然后随着每一个新的步骤,更多的菜单项被添加到测试越来越多的类功能。因此,最初,我为他们提供了一个文件来制定一个简单的菜单,然后随着他们朝着一个完整的解决方案前进,我为他们提供了更多的文件来驱动和检查他们的新程序。这可以这样做:

// --- File MenuStep1.cs ---
partial class Menu
{
    // This array is populated with more and more items at every new steps
    readonly List<MenuItem> MenuItems = new List<MenuItem>();

    public void Show()
    {
        // Code to show menu here
    }

    // Suppose we have a Main here, but that's not necessary
    public static void Main()
    {
        new Menu().Show();   
    }

    // These are hooking methods to add menu items later
    partial void InitStep2();
    partial void InitStep3();
    partial void InitStep4();

    public Menu()
    {
        InitStep1();
        InitStep2();
        InitStep3();
        InitStep4();
    }

    void InitStep1()
    {
        // Code that adds menu items, but only for step 1
    }
}

请注意,由于尚未定义部分方法 InitStep2、3 和 4,因此不会调用它们(甚至不会编译它们)。后来我为他们提供了自动扩展菜单的文件,如下所示:

// --- File MenuStep2.cs ---
partial class Menu
{
    partial void InitStep2()
    {
        // Code that adds more menu items
    }
}

,

// --- File MenuStep3.cs ---
partial class Menu
{
    partial void InitStep3()
    {
        // Code that adds more menu items
    }
}

等等。

于 2018-10-15T09:17:41.187 回答
-1

除了马特伯兰兹在该答案的评论中回答约翰逊的后续问题:

我自己从未创建过它们,但我想到了一些小的用途:

  • 使用部分方法来创建类似于抽象类或接口的东西。基本上,通过这种方式可以使用“可选方法”,使其能够删除方法实现,而不必删除它们各自的调用并最终重新实现它
  • 使用部分方法能够在同一基础上构建具有不同实现的多个项目。您可以有一个构建过程,允许您在不同的实现之间进行选择,这些实现反映在不同的部分类中。“基类”将具有方法签名,而不同的“实现类”、“implementA.cs”和“implementB.cs”将具有不同的实现。这样,您可以例如创建开发-测试-和发布实现或用户1-用户2和用户3实现。很酷的事情是你不必在运行时区分这些东西。相反,您将能够分发已经指定到该程度的“干净”版本。

我还要指出可能替代您尝试使用部分方法实现的差异的差异。

  • 事件 - 部分方法可以像事件一样使用。如果它们没有实现,它们将被忽略(它们甚至不在编译结果中)。但是事件有区别。虽然您可以为一个事件使用多个处理程序,但您只能实现一次部分方法!
  • 抽象类和接口——部分类/方法可以像抽象类一样使用,而不必实现方法并将其留空。如果您知道给定的抽象类会经常发生这种情况(首先显然检查您的架构,它可能有缺陷),您可以改用部分方法

另一种用途可能是为某人提供基本功能。你可以做我称之为“自下而上”的事情,这意味着你创造了一些东西,人们将它用作基础,在它之上构建,像工具一样使用它。或者您可以“自上而下”提供它。意思是,您已经实现了组件协同工作的方式,但是其他人可能会定义这些组件在内部的确切作用,例如我想构建一张桌子,我已经实现了它是一个有四个腿的盘子,但我把它留给用户选择腿的形状。这通常与生成的代码一起使用,以在一个类中编写生成的和 semf 生成的代码,但在不同的 .cs 文件中。

注意力

综上所述,这些可能不是实现这些目标的最佳方式。有多种方法可以做那些不需要部分方法的事情,并且可能更适合您想要做的事情。但也许这些可以让您了解如何使用部分方法。这实际上取决于您需要做什么,但了解硬件部分类的工作可能在将来很有用。

于 2018-07-18T14:48:26.287 回答