拆分/组合部分方法

我了解部分方法可用于跨多个文件拆分方法的定义。 我很好奇,但是允许跨多个文件的方法的每个定义都包含代码吗?

例如,假设我有一个方法private partial void Foo() 。 假设我已经在文件A和文件B中定义了它。两个实例都可以包含方法中的代码,还是只包含其中一个? 如果允许,我想我会感到惊讶。

不,你不能。 如果可以的话,当你调用Foo() ,哪个代码会先执行? 如果两个版本都在处理(和修改)全局状态,那么了解执行顺序就非常重要。

无论如何,这没有任何意义。 所以不,你不能

令人讨厌的例子1

作为从这种可能性中产生的不稳定行为的潜在肮脏的一个简单例子,假设你可以,并假设你有以下代码:

 public partial class MyClass { private int count = 0; public partial void NastyMethod() { count++; } } public partial class MyClass { public partial void NastyMethod() { Console.WriteLine(count); } } 

当你调用NastyMethod() ,它会打印什么值? 没意思!

令人讨厌的例子2

现在另一个奇怪的问题 如何处理参数? 并返回值?

 public partial class MyClass2 { public partial bool HasRealSolution(double a, double b, double c) { var delta = b*b - 4*a*c; return delta >= 0; } } public partial class MyClass2 { public partial void HasRealSolution(double a, double b, double c) { return false; } } 

现在,怎么可能对这段代码有所了解? 调用HasRealSolution(1, 2, 1)后我们应该考虑哪个回归? 如何为单一方法提供2个不同的同时返回值* ? 我们不处理非确定性有限自动机 !

对于那些在这个假设世界中强加的人,我不存在的部分方法应该是void ,用一些私有字段的值设置为该类来替换return s。 效果几乎相同。

*请注意,我在这里所说的不是由两个值组成的单个返回值,例如元组。 我在这里谈论两个返回值。 (???)

这实际上是对@ Bruno答案的评论,可能与这个问题没有完全相关

不允许部分方法具有多个实现的决定是在语言设计中做出的任意决定。 你的论点是一个很好的理由,为什么你可能决定不用你的语言允许这样的东西但是没有真正的技术限制。 您可以非常轻松地决定允许多个实现,并让编译器决定实现的执行顺序。 实际上,C#规范已经存在partial类的未定义顺序的情况:

 // A.cs: partial class Program { static int x = y + 42; static void Main() { System.Console.WriteLine("x: {0}; y: {1}", x, y); } } // B.cs: partial class Program { static int y = x + 42; } 

根据C#规范v3.0,这是有效的C#,但输出可以是:

 x: 42; y: 84 

要么

 x: 84; y: 42 

并且允许编译器生成它们中的任何一个。 它甚至不会产生警告。

C#语言需要部分方法来获得void返回类型。 部分方法签名最多可以定义一次。 同样,实施应该最多定义一次。

不可以。只有部分版本的部分方法可能包含代码。 使用实现定义部分方法的多个实现将导致编译器错误。

不,这是不可能的。 另外,你有一点误会。 部分方法的目的不是“跨多个文件拆分方法的定义”。

相反, 部分方法旨在将类的定义分割为多个文件。 这很有用,特别是对于自动生成的代码,因为它允许您定义可自由实现的“可选”方法,但也可以自由忽略。

正如响应者之一所指出的那样,在部分类的多个部分中排除多个部分方法实现没有技术原因。 它现在很流行,即使根据Microsoft DOC来创建将在Silverlight中运行的程序集,也可以在完整的CLR下运行,具体取决于所包含的文件。 Microsoft自己的示例包括Silverlight兼容文件中的部分方法定义,其实现包含在将包含在CLR构建中的其他文件中。

当然,如果允许多个实现,开发人员必须意识到调用顺序是非确定性的。 一个例子是一个方法,该方法对bool进行了单一引用,表明当前环境能够做“某事”。

一个例子:

 ///  /// Method will determine whether a type is serializable. ///  ///  /// The Type to be checked for serializability. ///  ///  /// ref variable to be set to true if serializable. If ///  is already true, the /// method should simply return. ///  

static partial void IsTheTypeSerializable(Type type,ref Boolean serializable);

这个方法可以用于框架的实现,该框架包括多个类型序列化选项,具体取决于混合的部分类的哪些部分以及包含的序列化器。 即使只有一个实现(所有可以在编译器规则下),实现必须遵循上面方法DOC中描述的逻辑,因为不能保证定义部分中的方法将在什么位置调用。 如果允许多个实现,则整体逻辑必须保证结果不依赖于实现的调用顺序。

在我们的框架中,我们实际上使用可加载的委托来执行不同场景的可序列化分析。 但是,确实可以方便地实现这种情况的多个实现。

我们猜测微软担心如果新手开发人员变得松散使用这个危险的function会导致混乱。 人们需要知道这样的事情是什么。

这是不可能的。 您可以在一个位置定义签名,并在另一个位置定义实现。

有关详细信息,请参阅MSDN 。

您无法合并方法,但可以使用“部分方法”设置链。 如果您想避免代码编织,这是一个选项。 我不是说这是一个很好的选择,但它是一个选择。

 public partial class MyClass { private int count = 0; public partial void NastyMethod() { count++; } } public partial class MyClass { public partial void NastyMethod() { Console.WriteLine(count); } } 

改变为。

 public partial class MyClass { private int count = 0; public partial void NastyMethod() { count++; OnNastyMethodExecuted(count); } partial void OnNastyMethodExecuted(int Value); } public partial class MyClass { partial void OnNastyMethodExecuted(int value) { Console.WriteLine(value); } } 
  • 部分方法由partial修饰符指示。
  • 部分方法必须是私有的。
  • 部分方法必须返回void。
  • 部分方法只能在部分类中声明。
  • 部分方法并不总是具有实现。
  • 部分方法可以是静态的和通用的。
  • 部分方法可以包含参数,包括ref但不能输出。
  • 您不能将委托委托给部分方法。

规则来自:

https://www.codeproject.com/Articles/30101/Introduction-to-Partial-Methods