如何构造带有许多默认参数的c#类并能够覆盖它们

本文关键字:覆盖 何构造 许多 参数 默认 | 更新日期: 2023-09-27 18:13:30

我正在编写一个具有成员变量的类。我想为这些字段定义默认值,并且必须能够使用自定义设置值覆盖它们。我想创建某种类或结构来保存这些变量的数据。我希望使用该类的人能够定义所有变量,或者如果他们不这样做,那么字段将被设置为默认值(我将定义)。不知道怎么做才最干净。这就是我的想法,但我不确定我是否能做得更好:

public class ReportPageParams 
{
    public float Width { get; private set; }
    public float Height { get; private set; }
    public float LeftMargin { get; private set; }
    public float RightMargin { get; private set; }
    public float TopMargin { get; private set; }
    public float BottomMargin { get; private set; }
    //Constructor
    ReportPageParams(float pWidth, pHeight) 
    {
        Width = 52f
        Height = 52f
        //...
    }
}
public class ReportPage  
{
    //same fields as ReportPageParams plus some more
    private float _width, _height;
    private float _leftMargin;
    private float _rightMargin;
    //...
    ReportPage(ReportPageParams pCustomParams = null) 
    {
        if (pCustomParams != null) 
        {
            _width = pCustomParams.Width
            _height = pCustomParams.Height
            //...
        }
        else
        {
            //set fields to default values
        }
    }
}

如何构造带有许多默认参数的c#类并能够覆盖它们

快速而肮脏的方法:将您的属性设置为protected set,然后创建一个从默认值派生的类。由于属性为protected,只有您的基类和派生类才能进行更改。

public class ReportPageParams
{
    public float Width { get; protected set; }
    public float Height { get; protected set; }
    public float LeftMargin { get; protected set; }
    public float RightMargin { get; protected set; }
    public float TopMargin { get; protected set; }
    public float BottomMargin { get; protected set; }
    //Constructor
    public ReportPageParams(float pWidth, float pHeight) 
    {
        Width = 52f
        Height = 52f
        //...
    }
}
public class ReportPageParamsWithLargeLeftMargin : ReportPageParams
{
    //Constructor
    public ReportPageParamsWithLargeLeftMargin(float pWidth, float pHeight)
        : base(pWidth, pHeight)
    {
        LeftMargin = 100;
    }
}

您会发现您在ReportPageParams的构造函数中设置的任何值也将出现在ReportPageParamsWithLargeLeftMargin中。因为构造函数是按照从最接近object的类到更具体的类的顺序执行的,所以您更改的默认值将被应用。

或者,您可以将属性设置为virtual,并派生一个类,用override覆盖它们。

如果你使用c# 6,你可以使用默认值为自动实现的属性:

public sealed class ImAComplex
{
    public float TypeWith { get; private set; } = 20.0f;
    public float LotsOf { get; private set; } = 40.0f;
    public float PropertiesWith { get; private set; } = 20.0f;
    public float DefaultValues { get; private set; } = 10.0f;
    public float ThatGoOn { get; private set; } = 40.0f;
    public float AndOn { get; private set; } = 20.0f;
    public float ForALong { get; private set; } = 90.0f;
    public float TimeBefore { get; private set; } = 12.5f;
    public float FinallyEnding { get; private set; } = 80.0f;
    // ... 
}

如果在此之前,仍然有选择保持你的公共界面干净。你只需要用老办法-

private float typeWith = 20.0f;
public float TypeWith
{
    get
    {
        return typeWith; 
    }
    private set
    {
        typeWith = value;
    }
}
// repeat ad nauseum
我喜欢的一种技术是使用静态工厂方法,因为您可以根据它们的函数("我返回什么样的ImaComplex"而不是"我返回一个ImAComplex")来命名它们,例如:
    public static ImAComplex WithBigTimeBefore(float typeWith, float lotsOf)
    {
        return new ImAComplex
        {
            TypeWith = typeWith,
            LotsOf = lotsOf, 
            TimeBefore = BigValue 
        };
    }

如果使用静态工厂方法,请确保将构造函数设置为私有。它像private ImAComplex() { }一样简单,可以防止外部代码实例化它。