Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现基类的必选集属性的最佳方法是什么?_C#_Inheritance - Fatal编程技术网

C# 实现基类的必选集属性的最佳方法是什么?

C# 实现基类的必选集属性的最佳方法是什么?,c#,inheritance,C#,Inheritance,我有一个关于C#和继承的简单基本问题 在下面的示例中,我展示了两种设置必须设置属性的方法(CaptionDisplayText和Firstname): 方法1,CaptionDisplayText,引入一个属性并在构造函数中设置它,而方法2引入一个抽象方法,该方法在派生类中被重写 我知道如果方法是虚拟的而不是抽象的,那么方法2是不好的,但是这里它是抽象的,这意味着它是在基类的构造函数之前执行的,这样就可以了 我有10-15个属性/字段,这些属性/字段必须由我的派生类设置,所以我想哪种方法更易于维

我有一个关于C#和继承的简单基本问题

在下面的示例中,我展示了两种设置必须设置属性的方法(CaptionDisplayText和Firstname):

方法1,CaptionDisplayText,引入一个属性并在构造函数中设置它,而方法2引入一个抽象方法,该方法在派生类中被重写

我知道如果方法是虚拟的而不是抽象的,那么方法2是不好的,但是这里它是抽象的,这意味着它是在基类的构造函数之前执行的,这样就可以了

我有10-15个属性/字段,这些属性/字段必须由我的派生类设置,所以我想哪种方法更易于维护、可读和测试

我认为方法1更易于测试,而方法2更易于阅读。方法2也是可测试的,因为模拟对象无论如何都必须实现抽象成员

你认为哪条路最好?还有第三条路吗


非常感谢,

您想过使用和ClassInvariant吗?

如果您确实想使类可测试,那么在构造函数中执行逻辑不是一种好办法。所以通过这样做。_firstName=this.GetFirstName();将引入额外的测试工作,即使您不想使用名字做任何事情,也会调用代码。在第一种方法中,您可以用null填充它,这表示它对您的测试不重要。

我认为最好的方法是第一种,因为它专门设置数据,并向调用者提供仅在构建对象期间必须设置的信息

这里唯一能遇到的“问题”是大量的属性,在这一点上,就像ctor中的参数一样,奇怪到可以在一个方法中看到15个参数。但这可能是可以通过ctor重载“避免”(我不知道你的应用程序,很难知道)的,如果你从一些属性值集合中扣除其他属性的“默认”值

显然也有字典/哈希集或任何解决方案,但对我来说,这个解决方案也很复杂

希望这有帮助


问候。

对我来说,这看起来很困惑。为什么要使用GetFirstName来设置名字。作为一个抽象的SetFirstName方法,并在其中执行逻辑,而不是将其隐藏在构造函数中,不是更好吗?我同意这是一种巧妙/不错的方法,但可能会让一些人感到困惑。在派生类中,当您实现GetFirstName方法时,在基类中设置它并不直观

类似于受保护的抽象字符串SetFirstName();这样,派生类总是必须重写此方法,并在其中设置第一个名称。当然,您必须保护firstname属性


这不是一个“必须设置”的方法。但至少给你一个暗示。或者,只需将GetFirstName更改为SetFirstName;)

我会使用一个可为空的字符串。这将迫使任何使用该类的人意识到这一事实。试图要求属性具有值的目的到底是什么。我假设这是某种类型的库?谢谢,但即使提供SetFirstName()抽象方法也不能保证将FirstName设置为派生类,因为该方法的主体可以为空;这就是为什么我没有提到这个选项。但我很感激它有两个好处:1)更好的可读性2)保持构造函数干净缺点:不能保证属性已设置。我完全同意。它不保证设置属性。但是需要指出的是,派生类也可以将get firstname方法留空,认为它没有被使用;是 啊它可以返回null,但由派生类决定设置什么,但这种方法可以确保属性被设置。我在2008年的一次会议上第一次看到codecontracts,我想当时微软的人已经开始研究它了,但它是为了确保一个方法传递了正确的参数,而不是问题这里。@William再看一看,代码契约也支持不变量和参数验证。感谢您的观点,但是当在构造函数中实例化10-15个属性时,会得到一个(丑陋=不好看)宽的构造函数。
public abstract class BaseClass
{
    private string _firstName;

    protected BaseClass(string captionDisplayText)
    {
        this.CaptionDisplayText = captionDisplayText;

        this._firstName = this.GetFirstName();
    }

    protected string CaptionDisplayText { get; private set; }

    protected abstract string GetFirstName();
}

public class DerivedClass : BaseClass
{
   protected DerivedClass():base(String.Empty)
   {

   }

   protected override string GetFirstName()
   {
       return String.Empty;
   }
}