我试图重构这个
class AClass
{
string Property1 { get; set; }
string Property2 { get; set; }
string Property3 { get; set; }
void AMethod(AClass other)
{
if(String.IsNullOrEmpty(this.Property1))
{
this.Property1 = other.Property1;
}
if(String.IsNullOrEmpty(this.Property2))
{
this.Property2 = other.Property2;
}
if(String.IsNullOrEmpty(this.Property3))
{
this.Property3 = other.Property3;
}
}
}
我唯一能想到的就是
private string GetFirstNotNullOrEmpty(string first, string second)
{
if (String.IsNullOrEmpty(first))
{
return second;
}
return first;
}
和
this.Property1 = GetFirstNotNullOrEmpty(this.Property1, other.Property1);
不完全相等,但可以完成任务。有没有更好的方法来重构它?
如果你打算对该类的N个字符串属性这样做,你应该使用反射来实现。
这都是关于"codez",对吧?是这样的:
class SomeClass
{
public string Property0 { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
public string Property4 { get; set; }
public string Property5 { get; set; }
public string Property6 { get; set; }
public string Property7 { get; set; }
public string Property8 { get; set; }
public string Property9 { get; set; }
public override string ToString()
{
//just to print out all properties and values
foreach (PropertyInfo prop in typeof(SomeClass).GetProperties())
{
Console.WriteLine(prop.Name + "," + prop.PropertyType + " = " + prop.GetValue(this, null));
}
return base.ToString();
}
public void CopyStringPropertiesIfEmptyFrom(SomeClass SourceInstance)
{
foreach (PropertyInfo prop in typeof(SomeClass).GetProperties())
{
if (prop.PropertyType == typeof(System.String) && String.IsNullOrEmpty((string)prop.GetValue(this, null)))
{
prop.SetValue(this, prop.GetValue(SourceInstance, null), null);
}
}
}
}
不使用方法,可以将if折叠成三元操作符:
this.Property1 = String.IsNullOrEmpty(this.Property1)? other.Property1 : this.Property1;
在属性中实现检查。
public class AClass
{
string Property1
{
get { return _Property1; }
set
{
if (String.IsNullOrEmpty(_Property1))
{
_Property1 = value
}
}
}
private string _Property1;
void AMethod(AClass other)
{
this.Property1 = other.Property1;// Property can only be set once.
}
}
当我可以避免使用反射时,我不是一个使用反射的粉丝,所以我实际上喜欢你在问题中建议的选项,但与Tesserex的回答稍微混合:
private string GetFirstNotNullOrEmpty(string first, string second)
{
return String.IsNullOrEmpty(first)) ? second : first;
}
我认为最好的解决方案是
private void SetFirstNotNullOrEmpty(string first, string second, Action<T> setter)
{
if (String.IsNullOrEmpty(first))
{
setter(second);
}
}
,它会像这样被调用:
this.Property1 = GetFirstNotNullOrEmpty(this.Property1, other.Property1, i => this.Property1 = i);
如果这些不是c#属性就更好了。使用公共字段,我可以传递引用,并在单个参数中同时使用getter和setter。
这里需要重构的第一件事是不直观的名称,如Property1和acclass。为类名和属性名使用有意义的名称,以便它们清楚地反映意图。
可能,OP想让我们关注手头的问题,而不是这个方面。