优化代码结构C#
Optimizing code structure C#
这是我编写的代码,用于在尝试更新数据库之前检查我的视图模型中的属性是否为空
var channel = _context.Channels.FirstOrDefault(x => x.Id == viewModel.Id);
if (!string.IsNullOrEmpty(viewModel.Part))
{
channel.Part = viewModel.Part;
}
if (!string.IsNullOrEmpty(viewModel.IndexName))
{
channel.IndexName = viewModel.IndexName;
}
if (viewModel.MeasurementId != null)
{
channel.MeasurementId = viewModel.MeasurementId;
}
if (!string.IsNullOrEmpty(viewModel.Direction))
{
channel.Direction = viewModel.Direction;
}
代码运行良好,但我在这里使用了很多 if 语句,这对我来说并不是很有效。你能建议我改变一下,比如使用其他语法或结构而不是 if 语句来使我的代码更简洁、更精巧 "pro"?
如果这些是字段而不是属性,您可以使用这样的东西:
void ReplaceIfNotEmpty(ref string destination, string source)
{
if (!string.IsNullOrEmpty(source))
{
destination = source;
}
}
然后就是
ReplaceIfNotEmpty(ref channel.Part, viewModel.Part);
如果只是 if
困扰您,您可以使用条件运算符:
channel.Part = string.IsNullOrEmpty(viewModel.Part) ?
channel.Part : viewModel.Part;
etc.
当然 总是 为 Part
调用 set
访问器,这很好,除非其中有逻辑(更改跟踪等)如果在值没有真正改变时调用它会很糟糕。
您也可以将条件运算符重构为一个方法,但没有其他方法 有条件地 设置值而不使用 if
。
只要您的通道对象的属性除了更改值(即触发事件)之外没有任何副作用,您就可以这样做:
string PickNonEmptyOrDefault(string value, string deflt)
{
return String.IsNullOrEmpty(value) ? deflt : value;
}
...
channel.Part = PickNonEmptyOrDefault(viewModel.Part, channel.Part);
channel.IndexName = PickNonEmptyOrDefault(viewModel.IndexName, channel.IndexName);
etc.
顺便说一句,我想知道是否有一种方法可以在不意外地影响您的 属性 的情况下完成此操作。诀窍是使用反射并使用 PropertyInfo
对象来完成您的工作:
class Foo
{
public string Bar { get; set; }
public string Baz { get; set; }
public override string ToString()
{
return (Bar ?? "") + " " + (Baz ?? "");
}
}
delegate void propsetter(string prop, string value);
private static void SetOnNonEmpty(PropertyInfo pi, Object o, string value)
{
if (pi.PropertyType != typeof(string))
throw new ArgumentException("type mismatch on property");
if (!String.IsNullOrEmpty(value))
pi.SetValue(o, value);
}
static void Main(string[] args)
{
var myObj = new Foo();
myObj.Baz = "nothing";
PropertyInfo piBar = myObj.GetType().GetProperty("Bar");
PropertyInfo piBaz = myObj.GetType().GetProperty("Baz");
SetOnNonEmpty(piBar, myObj, "something");
SetOnNonEmpty(piBaz, myObj, null);
Console.WriteLine(myObj);
}
输出something nothing
老实说,我不建议这样做,因为它并没有真正增加可读性,而且感觉很恶心。
我更倾向于编写一段代码来反映您的视图模型的属性并调用 Func<string, string>
以在您的数据模型中获取相应的 属性 名称,然后如果 returns 非空且 属性 类型匹配,则在视图对象上调用 getter 并将其传递给数据对象上的 setter。
只有当我多次这样做时,我才会这样做。
你写的代码绝对没有问题。
如果您的 objective 代码行数较少,您可以这样做,但我认为这只会增加不必要的复杂性。
channel.Part = string.IsNullOrWhiteSpace(viewModel.Part) ? channel.Part : viewModel.Part;
channel.IndexName = string.IsNullOrWhiteSpace(viewModel.IndexName) ? channel.IndexName: viewModel.IndexName;
channel.MeasurementId = viewModel.MeasurementId == null ? channel.MeasurementId : viewModel.MeasurementId;
channel.Direction = string.IsNullOrWhiteSpace(viewModel.Direction) ? channel.Direction : viewModel.Direction;
请注意,我已将您的呼叫从 IsNullOrEmpty 切换到 IsNullOrWhiteSpace
值为“ ”(一个或多个空格)的字符串将通过 IsNullOrEmpty 检查,您可能不希望这样做。
您还可以像这样对可空类型(但不是空字符串)使用合并运算符...
channel.MeasurementId = viewModel.MeasurementId ?? channel.MeasurementId;
你的代码没问题。甚至 Jon Skeet 使用 if
语句。
如果您想要性能最佳的代码,请保持这样。如果您想让您的代码看起来 pro,请使用此处其他人提出的任何建议。我的意见:保持原样。
这是我编写的代码,用于在尝试更新数据库之前检查我的视图模型中的属性是否为空
var channel = _context.Channels.FirstOrDefault(x => x.Id == viewModel.Id);
if (!string.IsNullOrEmpty(viewModel.Part))
{
channel.Part = viewModel.Part;
}
if (!string.IsNullOrEmpty(viewModel.IndexName))
{
channel.IndexName = viewModel.IndexName;
}
if (viewModel.MeasurementId != null)
{
channel.MeasurementId = viewModel.MeasurementId;
}
if (!string.IsNullOrEmpty(viewModel.Direction))
{
channel.Direction = viewModel.Direction;
}
代码运行良好,但我在这里使用了很多 if 语句,这对我来说并不是很有效。你能建议我改变一下,比如使用其他语法或结构而不是 if 语句来使我的代码更简洁、更精巧 "pro"?
如果这些是字段而不是属性,您可以使用这样的东西:
void ReplaceIfNotEmpty(ref string destination, string source)
{
if (!string.IsNullOrEmpty(source))
{
destination = source;
}
}
然后就是
ReplaceIfNotEmpty(ref channel.Part, viewModel.Part);
如果只是 if
困扰您,您可以使用条件运算符:
channel.Part = string.IsNullOrEmpty(viewModel.Part) ?
channel.Part : viewModel.Part;
etc.
当然 总是 为 Part
调用 set
访问器,这很好,除非其中有逻辑(更改跟踪等)如果在值没有真正改变时调用它会很糟糕。
您也可以将条件运算符重构为一个方法,但没有其他方法 有条件地 设置值而不使用 if
。
只要您的通道对象的属性除了更改值(即触发事件)之外没有任何副作用,您就可以这样做:
string PickNonEmptyOrDefault(string value, string deflt)
{
return String.IsNullOrEmpty(value) ? deflt : value;
}
...
channel.Part = PickNonEmptyOrDefault(viewModel.Part, channel.Part);
channel.IndexName = PickNonEmptyOrDefault(viewModel.IndexName, channel.IndexName);
etc.
顺便说一句,我想知道是否有一种方法可以在不意外地影响您的 属性 的情况下完成此操作。诀窍是使用反射并使用 PropertyInfo
对象来完成您的工作:
class Foo
{
public string Bar { get; set; }
public string Baz { get; set; }
public override string ToString()
{
return (Bar ?? "") + " " + (Baz ?? "");
}
}
delegate void propsetter(string prop, string value);
private static void SetOnNonEmpty(PropertyInfo pi, Object o, string value)
{
if (pi.PropertyType != typeof(string))
throw new ArgumentException("type mismatch on property");
if (!String.IsNullOrEmpty(value))
pi.SetValue(o, value);
}
static void Main(string[] args)
{
var myObj = new Foo();
myObj.Baz = "nothing";
PropertyInfo piBar = myObj.GetType().GetProperty("Bar");
PropertyInfo piBaz = myObj.GetType().GetProperty("Baz");
SetOnNonEmpty(piBar, myObj, "something");
SetOnNonEmpty(piBaz, myObj, null);
Console.WriteLine(myObj);
}
输出something nothing
老实说,我不建议这样做,因为它并没有真正增加可读性,而且感觉很恶心。
我更倾向于编写一段代码来反映您的视图模型的属性并调用 Func<string, string>
以在您的数据模型中获取相应的 属性 名称,然后如果 returns 非空且 属性 类型匹配,则在视图对象上调用 getter 并将其传递给数据对象上的 setter。
只有当我多次这样做时,我才会这样做。
你写的代码绝对没有问题。
如果您的 objective 代码行数较少,您可以这样做,但我认为这只会增加不必要的复杂性。
channel.Part = string.IsNullOrWhiteSpace(viewModel.Part) ? channel.Part : viewModel.Part;
channel.IndexName = string.IsNullOrWhiteSpace(viewModel.IndexName) ? channel.IndexName: viewModel.IndexName;
channel.MeasurementId = viewModel.MeasurementId == null ? channel.MeasurementId : viewModel.MeasurementId;
channel.Direction = string.IsNullOrWhiteSpace(viewModel.Direction) ? channel.Direction : viewModel.Direction;
请注意,我已将您的呼叫从 IsNullOrEmpty 切换到 IsNullOrWhiteSpace
值为“ ”(一个或多个空格)的字符串将通过 IsNullOrEmpty 检查,您可能不希望这样做。
您还可以像这样对可空类型(但不是空字符串)使用合并运算符...
channel.MeasurementId = viewModel.MeasurementId ?? channel.MeasurementId;
你的代码没问题。甚至 Jon Skeet 使用 if
语句。
如果您想要性能最佳的代码,请保持这样。如果您想让您的代码看起来 pro,请使用此处其他人提出的任何建议。我的意见:保持原样。