拆分/组合部分方法

Ran*_*der 18 c#

我了解部分方法可用于跨多个文件拆分方法的定义.我很好奇,如果允许跨多个文件的方法的每个定义包含代码?

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

Bru*_*eis 20

不,你不能.如果可以,当你打电话时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);
    }
}
Run Code Online (Sandbox Code Playgroud)

当你打电话时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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

对于那些在这个假设的世界中强加我不存在的部分方法的人来说void,将returns 替换为在某个私有领域设置一个值.效果几乎相同.

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

  • 从理论上讲,语言可以有一个构造来处理这种情况(事实并非如此). (8认同)
  • @Bruno:`partial`方法必须是`void`. (5认同)
  • @Bruno:在部分类的不同部分定义的初始化表达式已经是这样的.订单无法保证.我同意你的看法,这是一个好主意,它不可能在C#中做到这一点,但它不是"原因"为什么不.这是不可能的,因为他们*选择*使其变得不可能,而不是因为存在技术限制. (4认同)
  • 给@Jason评论+1 - @Bruno:虽然这不是一个令人信服的理由.它可以在不保证执行顺序的情况下顺序执行(这会有点令人困惑,但肯定是可能的). (2认同)
  • @Mehrdad,这将是一个非常脆弱的架构.无论如何,它没有任何意义. (2认同)

Meh*_*ari 20

这实际上是对@ 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;
}
Run Code Online (Sandbox Code Playgroud)

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

x: 42; y: 84
Run Code Online (Sandbox Code Playgroud)

要么

x: 84; y: 42
Run Code Online (Sandbox Code Playgroud)

并允许编译器生成其中任何一个.它甚至不会产生警告.

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

  • @Bruno:我认为`partial`应保留用于代码生成目的.如果真的需要将单个类中的东西分成多个文件,那么该类可能太大而且应该分成多个类. (2认同)

Jar*_*Par 8

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

  • +1.实际上,*声明*部分`方法的多个实例也是一个错误.最多可以存在一个声明和一个实现. (3认同)

Ree*_*sey 5

不,这是不可能的.此外,你有一点误会.部分方法的目的不是"跨多个文件拆分方法的定义".

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