我对C#很新,所以请耐心等待......
我正在实现一个部分类,并希望添加两个属性,如:
public partial class SomeModel
{
public bool IsSomething { get; set; }
public List<string> SomeList { get; set; }
... Additional methods using the above data members ...
}
我想初始化两个数据成员:IsSomething
到True
和SomeList
到new List<string>()
。通常我会在构造函数中执行它,但是因为它是一个部分类我不想触及构造函数(我应该吗?)。
实现这一目标的最佳方式是什么?
由于
PS我在ASP.NET MVC中工作,为某个模型添加功能,因此是部分类。
答案 0 :(得分:37)
针对C#6进行了更新
C#6增加了为自动属性分配默认值的功能。值可以是任何表达式(它不必是常量)。以下是一些例子:
// Initialize to a string literal
public string SomeProperty {get;set;} = "This is the default value";
// Initialize with a simple expression
public DateTime ConstructedAt {get;} = DateTime.Now;
// Initialize with a conditional expression
public bool IsFoo { get; } = SomeClass.SomeProperty ? true : false;
原始答案
自动实现的属性可以在类构造函数中初始化,但不能在属性本身上初始化。
public SomeModel
{
IsSomething = false;
SomeList = new List<string>();
}
...或者您可以使用字段支持的属性(稍微多一些工作)并初始化字段本身......
private bool _IsSomething = false;
public bool IsSomething
{
get { return _IsSomething; }
set { _IsSomething = value; }
}
更新:我的上述答案并没有说明这部分课程的问题。 Mehrdad's answer提供了使用部分方法的解决方案,这符合我的第一个建议。我的第二个建议是使用非自动实现的属性(手动实现的属性?)将适用于这种情况。
答案 1 :(得分:8)
第一个属性(IsSomething)是一个布尔值。默认情况下它会是假的。
第二个属性,因为它是一个引用类型,默认为null而不需要你做任何努力。您不需要触摸构造函数,因为引用类型(类)将在.NET中自动从null开始。
如果您想使用非默认值,则有两个选项 -
首先,使用后备存储字段:
private bool isSomething = true;
public bool IsSomething {
get { return this.isSomething; }
set { this.isSomething = value; }
}
第二个选项 - 将其添加到构造函数中。
请注意,第一个选项没有额外开销 - 它基本上是编译器在使用自动属性时所执行的操作。
答案 2 :(得分:5)
在部分类的两个部分中不能有两个构造函数。但是,您可以使用partial methods来完成类似的操作:
// file1:
partial void Initialize();
public Constructor() {
// ... stuff ... initialize part 1
Initialize();
}
// file2:
void Initalize() {
// ... further initializations part 2 might want to do
}
如果partial类的任何部分都没有定义partial方法,则对它的所有调用都将被省略。
答案 3 :(得分:5)
WCF分部类用户的警告
如果您尝试将属性添加到WCF代理类(由“添加服务引用”生成),您可能会惊讶地发现私有字段未初始化,因为显然no constructor at all is called。
如果您尝试这样做(如其他一些答案中所建议的那样),则不会被调用:
private bool _sendEmail = true;
这与字段是否属于部分类无关。
您需要做的是添加[OnDeserialized]属性,该属性允许您对对象进行进一步初始化。这是System.Runtime.Serialization的一部分,因此仅在使用DataContractSerializer时序列化的上下文中有用。
public partial class EndOfDayPackageInfo
{
[OnDeserialized()]
public void Init(StreamingContext context)
{
_sendEmail = true;
}
private bool _sendEmail;
public bool SendEmail
{
get
{
return _sendEmail;
}
set
{
_sendEmail = value;
RaisePropertyChanged("SendEmail");
}
}
}
另一种方法是'延迟加载'属性 - 但这种方法不那么优雅。
private bool _sendEmail;
private bool _sendEmailInitialized;
public bool SendEmail
{
get
{
if (!_sendEmailInitialized)
{
_sendEmailInitialized = true;
_sendEmail = true; // default value
}
return _sendEmail;
}
set
{
if (!_sendEmailInitialized)
{
// prevent unwanted initialization if 'set' is called before 'get'
_sendEmailInitialized = true;
}
_sendEmail = value;
RaisePropertyChanged("SendEmail");
}
}
答案 4 :(得分:4)
为此,请不要使用自动属性,而是使用旧方式
YourType _yourParameter = yourDefaultValue;
public YourType YourParameter
{
get{return _yourParameter;}
set{_yourParameter=value;}
}
答案 5 :(得分:3)
对于C#6.0版的用户,可以初始化这样的属性:
public bool IsSomething { get; set; } = true;
public List<string> SomeList { get; set; } = new List<string>();
答案 6 :(得分:1)
您的属性都已具有您需要的默认值。
在部分类中使用构造函数没有任何问题。部分类绝不是特殊的,除了它们的源代码分布在多个文件/声明之外。
答案 7 :(得分:0)
private bool _InternalUserContactUpdate = false;
public bool InternalUserContactUpdate
{
get { return _InternalUserContactUpdate; }
set { _InternalUserContactUpdate = value; }
}
然后当你想覆盖条件上的值时,
if(!objUserModel.FirstName.ToLower().Equals(entry.Key[0].Attributes.Contains("firstname").ToString().ToLower()))
{
objUserModel.InternalUserContactUpdate= true;
}
希望这会有所帮助