如何构建具有许多默认参数的 C# Class 并能够覆盖它们

How to Construct C# Class with Many Default Paramters and Have Ability to Override Them

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

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
        }
    }
}

快速而肮脏的方法:创建您的属性 protected set,然后创建一个从您的默认值派生的 class。由于属性为 protected.

,因此只有您的基础和派生 classes 才能进行更改
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 的 class 到更具体的 class 的顺序执行的,所以将应用您更改的默认值。

或者,您可以创建属性 virtual 并派生一个 class 用 override 覆盖它们。这让您负责自己处理 属性。

如果您使用的是 C# 6,则可以使用 default values for auto implemented properties

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;

    // ... 
}

如果在那之前,仍然可以选择保持 public 面向界面的清洁。你只需要用老式的方式来做 -

private float typeWith = 20.0f;
public float TypeWith
{
    get
    {
        return typeWith; 
    }
    private set
    {
        typeWith = value;
    }
}
// repeat ad nauseum

我喜欢的一种技术是使用静态工厂方法,我喜欢它是因为您可以根据它们的功能来命名它们("what kind of ImaComplex does I return" 而不是 "I return an ImAComplex"),例如:

    public static ImAComplex WithBigTimeBefore(float typeWith, float lotsOf)
    {
        return new ImAComplex
        {
            TypeWith = typeWith,
            LotsOf = lotsOf, 
            TimeBefore = BigValue 
        };
    }

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