【问题标题】:class modifier issues in C# with "private" classesC# 中带有“私有”类的类修饰符问题
【发布时间】:2011-02-19 05:50:33
【问题描述】:

我有一个有很多方法的类:

public class MyClass {
    public bool checkConditions() {
        return checkCondition1() &&
               checkCondition2() &&
               checkCondition3();
    }

...conditions methods

    public void DoProcess() {
        FirstPartOfProcess();
        SecondPartOfProcess();
        ThirdPartOfProcess();
    }

...process methods
}

我确定了两个“重要”工作领域,并决定将这些方法提取到自己的类中:

public class MyClass {
    private readonly MyClassConditions _conditions = new ...;
    private readonly MyClassProcessExecution = new ...;

    public bool checkConditions() {
        return _conditions.checkConditions();
    }

    public void DoProcess() {
        _process.DoProcess();
    }
}

在 Java 中,我将 MyClassConditionsMyClassProcessExecution 定义为 package protected,但在 C# 中我不能这样做。


您将如何在 C# 中执行此操作?

将两个类都设置为 MyClass 的内部类?

我有 2 个选项:要么在 MyClass 中定义它们,将所有内容都放在同一个文件中,这看起来令人困惑和丑陋,要么我可以将 MyClass 定义为 partial class,为 MyClass 定义一个文件,其他为MyClassConditions,其他为MyClassProcessExecution

将它们定义为内部?

我不太喜欢内部修饰符,因为我发现这些类根本没有为我的程序/程序集的其余部分增加任何价值,如果可能的话,我想隐藏它们。它们在程序的任何其他部分都不会有用/可重用。

保持公开?

我不明白为什么,但我在这里选择了这个选项。

还有其他的吗?

给它命名!

谢谢

【问题讨论】:

    标签: c# .net private nested-class internal


    【解决方案1】:

    对于不会在当前程序集之外使用的“Helper”类型类,如果方法将被多个类使用,Internal 是要走的路。

    对于仅由单个类使用的方法,我只会将它们设为该类的私有类,或者如果它实际上是一个在其他任何地方都没有使用的类,则使用内部类。如果代码不依赖类的任何(非静态)成员,您也可以将代码分解为静态方法。

    【讨论】:

    • 是的,它们不会在程序集之外使用。但它们也不应该在课程本身之外使用:(
    • 是的,我编辑了我的答案以反映这种担忧。我不是内部类的忠实拥护者,因为它们往往会使代码混乱(IMO),但如果它们没有在其他任何地方使用,你可以在这里为它辩护。
    • 我认为将代码分解为静态方法没有任何优势。方法还在,有什么好处?
    • Stackoverflow 是你的朋友 ;) (stackoverflow.com/questions/135020/…)
    • 我认为与 OP 的要求相比没有任何优势。
    【解决方案2】:

    您最好的选择可能是使用部分类并将三组代码放在单独的文件中,添加到同一个类中。然后,您可以将条件和过程代码设为私有,以便只有类本身可以访问它们。

    【讨论】:

      【解决方案3】:

      使用与您重构的方法相同的访问修饰符创建类。仅当您有多个人或自动代码生成工具经常修改相同的类时,部分类才真正有用。他们只是真正避免了源代码合并地狱,因为它无法将多个编辑合并到同一个文件中。

      【讨论】:

        【解决方案4】:

        我可以 将 MyClass 定义为部分类, 一个文件用于 MyClass,另一个用于 MyClassConditions 和其他用于 MyClassProcessExecution。

        也许这是我的 C++ 背景,但这是我的标准方法,尽管我将小型帮助程序类捆绑到一个文件中。

        因此,在我当前的一个项目中,Product 类分为 Product.csProductPrivate.cs

        【讨论】:

          【解决方案5】:

          我打算做点别的——公共/受保护/私有的问题可能无法通过这个专门解决,但我认为它比许多嵌套的内部类更适合维护。

          因为听起来您在顺序算法中有一组步骤,其中一个步骤的执行可能取决于也可能不取决于上一步的执行。这种类型的顺序步骤处理有时可以使用Chain of Responsibility 模式,尽管它与最初的意图有所不同。仅关注您的“处理方法”,例如,从以下内容开始:

          class LargeClass
          {
          public void DoProcess()
          {
            if (DoProcess1())
            {
              if (DoProcess2())
              {
                DoProcess3();
              }
            }
          }
          
          protected bool DoProcess1()
          {
          ...
          }
          
          protected bool DoProcess2()
          {
          ...
          }
          
          protected bool DoProcess3()
          {
          ...
          }
          
          }
          

          使用责任链,这可以分解为每个步骤的一组具体类,这些类继承自一些抽象步骤类。如果满足必要的先决条件,抽象步骤类更负责确保调用下一步。

          public class AbstractStep
          {
              public AbstractStep NextStep { get; set; }
          
              public virtual bool ExecuteStep
              {
                 if (NextStep != null)
                 {
                   return NextStep.ExecuteStep();
                 }
              }  
          }
          
          public class ConcreteStep1 : AbstractStep
          {
              public bool ExecuteStep
              {
                 // execute DoProcess1 stuff
                 // call base
                 return base.ExecuteStep();
              }
          }
          
          ...
          
          public class ConcreteStep3 : AbstractStep
          {
               public bool ExecuteStep
               { 
                  // Execute DoProcess3 stuff
                  // call base
                  return true; // or false?
                }
          }
          

          要进行设置,您可以在代码的某些部分执行以下操作:

          var stepOne = new ConcreteStep1();
          var stepTwo = new ConcreteStep2();
          var stepThree = new ConcreteStep3();
          stepOne.NextStep = stepTwo;
          stepTwo.NextStep = stepThree;
          
          bool success = stepOne.ExecuteStep();
          

          这可能有助于清理您在单个类中遇到的代码膨胀 - 我过去曾将它用于一些顺序类型算法,它有助于很好地隔离每个步骤。您显然可以将相同的想法应用于您的条件检查(或将它们构建到每个步骤中,如果适用的话)。您还可以通过让 ExecuteStep 方法采用带有某种状态对象的参数来在步骤之间传递状态方面对此进行一些变化。

          当然,如果您在这篇文章中真正关心的只是隐藏各个步骤,那么是的,您可以将每个子步骤设置为创建步骤的类中的受保护类。但是,除非您以某种形式或方式向客户公开您的库,并且您不希望他们对您的执行步骤有任何类型的可见性,否则与使代码可维护相比,这似乎是一个较小的问题。

          【讨论】:

            猜你喜欢
            • 2014-08-27
            • 2016-06-03
            • 1970-01-01
            • 1970-01-01
            • 2020-08-23
            • 2011-05-03
            • 2016-08-21
            • 2017-12-22
            • 1970-01-01
            相关资源
            最近更新 更多