如何构建具有许多默认参数的 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() { }
一样简单。
我正在写一个带有成员变量的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
.
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() { }
一样简单。