如何在C#3.0中使用部分方法?

时间:2008-09-03 17:42:42

标签: c# design-patterns .net-3.5 partial-methods

我已经阅读了最新C# language specification中的部分方法,所以我理解了原理,但我想知道人们是如何使用它们的。是否有特定的设计模式可以从部分方法中受益?

5 个答案:

答案 0 :(得分:23)

部分方法的引入与类似的原因有关,为什么部分类在.Net 2中。

部分类是可以跨多个文件分割的类 - 编译器在运行时将它们全部构建到一个文件中。

这样做的好处是Visual Studio可以为类的一部分提供图形设计器,而编码器可以在另一个上工作。

最常见的例子是表单设计器。开发人员不希望在大多数时间手动定位按钮,输入框等。

  • 在.Net 1中,它是#region
  • 中的自动生成代码
  • 在.Net 2中,这些成为独立的设计者类 - 表单仍然是一个类,它只是分成一个由开发人员编辑的文件和一个由表单设计者编辑的文件

这使维护两者变得更容易。合并更简单,VS表单设计人员意外撤消编码人员手动更改的风险较小。

在.Net 3.5中引入了Linq。 Linq有一个DBML设计器,用于构建数据结构,并生成自动代码。

这里的额外部分是提供开发人员可能想要填写的方法所需的代码。

由于开发人员将扩展这些类(使用额外的部分文件),因此无法在此处使用抽象方法。

另一个问题是,大多数情况下这些方法都不会被调用,并且调用空方法是浪费时间。

空方法are not optimised out

因此Linq生成空的部分方法。如果你没有创建自己的部分来完成它们,那么C#编译器就会优化它们。

这样它可以做到这一点,部分方法总是返回void。

如果您创建一个新的Linq DBML文件,它将自动生成一个部分类,如

[System.Data.Linq.Mapping.DatabaseAttribute(Name="MyDB")]
public partial class MyDataContext : System.Data.Linq.DataContext
{
    ...

    partial void OnCreated();
    partial void InsertMyTable(MyTable instance);
    partial void UpdateMyTable(MyTable instance);
    partial void DeleteMyTable(MyTable instance);

    ...

然后在您自己的部分文件中,您可以扩展它:

public partial class MyDataContext
{
    partial void OnCreated() {
        //do something on data context creation
    }
}

如果你不扩展这些方法,他们就会得到优化。

部分方法不能公开 - 因为它们必须在那里供其他类调用。如果您编写自己的代码生成器,我可以看到它们很有用,但除此之外它们只对VS设计器有用。

我之前提到的例子是一种可能性:

//this code will get optimised out if no body is implemented
partial void DoSomethingIfCompFlag();

#if COMPILER_FLAG
//this code won't exist if the flag is off
partial void DoSomethingIfCompFlag() {
    //your code
}
#endif

另一个潜在的用途是,如果您有一个庞大而复杂的类溢出多个文件,您可能希望在调用文件中进行部分引用。但是我认为在这种情况下你应该考虑先简化课程。

答案 1 :(得分:10)

部分方法在概念上与GoF Template Method行为模式(Design Patterns,p325)非常相似。

它们允许在一个地方定义算法或操作的行为,并在其他地方实现或更改,从而实现可扩展性和自定义。我已经开始在C#3.0中使用部分方法而不是模板方法,因为我认为代码更清晰。

一个很好的特性是未实现的部分方法在编译时不会产生运行时开销。

答案 2 :(得分:2)

Code generation 是其存在的主要原因之一,也是使用它们的主要原因之一。


编辑:即使该链接是针对Visual Basic特定的信息,相同的基本原则也与C#相关。

答案 3 :(得分:2)

我将它们视为轻量级事件。您可以拥有可重复使用的代码文件(通常是自动生成但不一定),并且对于每个实现,只需处理您在分部类中关注的事件。事实上,这就是它在LINQ to SQL中的使用方式(以及为什么语言功能被发明)。

答案 4 :(得分:0)

以下是C#.NET 3.0中部分类的最佳资源:http://msdn.microsoft.com/en-us/library/wa80x488(VS.85).aspx

我尽量避免使用部分类(Visual Studio为设计器文件创建的部分除外;这些都很棒)。对我而言,将一个类的所有代码放在一个地方更为重要。如果你的课程设计得很好并代表一件事(single responsibility principle),那么这一件事的所有代码应该在一个地方。