如何构造带有许多默认参数的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
}
}
}
快速而肮脏的方法:将您的属性设置为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() { }
一样简单,可以防止外部代码实例化它。