优化代码结构C#

时间:2015-03-04 21:33:12

标签: c# asp.net-mvc if-statement

这是我编写的代码,用于在尝试更新数据库之前检查我的viewmodel中的属性是否为null

   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语句来使我的代码更简洁并且更加“专业”?

5 个答案:

答案 0 :(得分:3)

只要您的频道对象的属性除了更改值(即触发事件)之外没有任何副作用,您可以这样做:

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>来获取数据模型中的相应属性名称,然后返回非null并且属性类型匹配,在视图对象上调用getter并将其传递给数据对象上的setter。

如果我这么做很多次,我只会这样做。

答案 1 :(得分:2)

如果它只是困扰你的if你可以使用条件运算符:

channel.Part = string.IsNullOrEmpty(viewModel.Part) ? 
               channel.Part : viewModel.Part;
etc.

当然总是调用set的{​​{1}}访问者,除非其中有逻辑(更改跟踪等),否则这样会很好如果在值没有真正改变时被调用,那就太糟糕了。

你也可以将条件运算符重构为一个方法,但是没有其他方法有条件地设置值而不使用Part

答案 2 :(得分:2)

您编写的代码绝对没有错。

如果您的目标是较少的代码行,您可以这样做,但我认为这只会增加不必要的复杂性。

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检查。

你也可以使用coalesce运算符为你的可空类型(但不是空字符串)...

channel.MeasurementId = viewModel.MeasurementId ?? channel.MeasurementId;

答案 3 :(得分:2)

你的代码很好。即使Jon Skeet使用if语句。

如果您想要性能最佳的代码,请保持这样。如果您想让代码看起来像 pro ,请使用其他人在此处提出的任何建议。我的意见是:保持原样。

答案 4 :(得分:0)

如果这些是字段而不是属性,则可以使用以下内容:

void ReplaceIfNotEmpty(ref string destination, string source)
{
    if (!string.IsNullOrEmpty(source))
    {
        destination = source;
    }
}

然后只是

ReplaceIfNotEmpty(ref channel.Part, viewModel.Part);