【问题标题】:How to Construct C# Class with Many Default Paramters and Have Ability to Override Them如何使用许多默认参数构造 C# 类并具有覆盖它们的能力
【发布时间】:2015-12-16 05:01:06
【问题描述】:

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

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#,您是否在 Visual Studio 2015 中编写代码?如果您有更多选择。
  • public float Width { get; private set; } = 1.222 or something 将为属性设置默认值

标签: c# .net class default-constructor


【解决方案1】:

快速而肮脏的方式:将您的属性设为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 覆盖它们的类。这让您自己负责处理财产。

【讨论】:

  • 您好,感谢您的解决方案。我喜欢这个。如果可以的话,我会将它与 jdphenix 的解决方案结合起来,但我没有使用 C# 6,所以我想我会坚持使用默认构造函数。
【解决方案2】:

如果你使用的是 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;

    // ... 
}

如果在此之前,您仍然可以选择保持面向公众的界面整洁。你只需要用老式的方式来做 -

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() { } 一样简单,可以防止外部代码实例化它。

【讨论】:

    猜你喜欢
    • 2013-10-27
    • 2018-04-08
    • 1970-01-01
    • 2015-06-30
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    相关资源
    最近更新 更多