在一个命令中更改对象的多个属性

时间:2018-12-16 10:16:09

标签: c#

这是一个具有三个属性的对象:

public class myClass
{
   public int score { get; set; }
   public string name { get; set; }
   public bool isAlive { get; set; }
}

在创建此类的实例后,在某些地方,我将更改该实例的两个或三个属性,如下所示:

targetInstance.score = 1;
targetInstance.name = "John";
targetInstance.isAlive = true;

有什么方法可以一次使用targetInstance,然后以某种方式使用一些方括号来设置属性(例如初始化),类似于以下内容:

targetInstance = { score = 1, name = "John" }

注意:也许您建议使用一种方法来接收这些值并更改属性,但是在属性太多的情况下不适用。

6 个答案:

答案 0 :(得分:5)

命名参数

您可以编写带有命名默认参数的方法,并使用命名参数仅更新所需的参数。

例如:

public class myClass
{
   public int score { get; set; }
   public string name { get; set; }
   public bool isAlive { get; set; }

   public void Set(int score = -1, string name = null, bool? isAlive = null)
   {
       if (score != -1) this.score = score;
       if (name != null) this.name = name;
       if (isAlive.HasValue) this.isAlive = isAlive.Value;
   }
}

您可以这样称呼它:

var o = new myClass();
o.Set(name: "Hello");

var o = new myClass();
o.Set(name: "Hello", isValid: false);

var o = new myClass();
o.Set(score: 100, isValid: false);

流利的语法

您可以创建一组可链接的“设置方法”,如下所示:

public class myClass
{
   public int score { get; set; }
   public string name { get; set; }
   public bool isAlive { get; set; }

   public myClass SetScore(int score)
   {
       this.score = score;
       return this;
   }

   public myClass SetName(string name)
   {
       this.name = name;
       return this;
   }

   public myClass SetIsAlive(bool isAlive)
   {
       this.isAlive = isAlive;
       return this;
   }
}

然后像这样使用它:

var o = new myClass();
o.SetName("Donald").SetIsAlive(true);

或者这样:

var o = new myClass()
    .SetName("Bob")
    .SetScore(0)
    .SetIsAlive(true);

答案 1 :(得分:4)

最接近的是使用C#7 tuples解构语法:

(targetInstance.score, targetInstance.name, targetInstance.isAlive) = (1, "John", true);

尽管它仍然需要重复目标变量名,所以Daniel Hilgarth的答案是正确的。

答案 2 :(得分:3)

您正在寻找VB中With关键字的等效项。
在C#中,没有任何内容。

答案 3 :(得分:1)

您可以将复制构造函数与对象初始化结合使用,当您要修改旧对象时可以新建一个全新的对象,也可以用新对象覆盖旧对象。像这样:

public class Person
{
    public Person() // this is your default constructor
    {
    }

    public Person(Person originalPerson) // this is your copy constructor
    {
        Name = originalPerson.Name;
        Surname = originalPerson.Surname;
        Address = originalPerson.Address;
        Age = originalPerson.Age;
    }

    public string Name;
    public string Surname;
    public string Address;
    public int Age;
}

public class Program
{
    static void Main(string[] args)
    {
        // create object with whatever properties you like
        var person1 = new Person
        {
            Name = "Max", Surname = "Mustermann", Age = 30,
        };

        // now rewrite the old object with the old properties and modify
        // any properties you like using object initialization
        person1 = new Person(person1)
        {
            Address = "Main Street 1",
            Age = 32,
        };

        // now person1 has the Name, Surname from 1st assignment
        // plus Address and Age from 2nd assignment (Age = 32)
    }
}

答案 4 :(得分:1)

作为一种选择,您可以创建一个With扩展方法:

public static class WithExtension
{
    public static void With<T>(this T o, Action<T> values)
    {
        values?.Invoke(o);
    }
}

然后以这种方式使用它:

person.With(p=>{
    p.Id = 1;
    p.Name = "Someone";
    p.BirthDate = DateTime.Now;
});

另一个选择:

public static class WithExtension
{
    public static void With(this object o, object values)
    {
        var props = TypeDescriptor.GetProperties(values);
        var sourceProps = TypeDescriptor.GetProperties(o);
        foreach (PropertyDescriptor p in props)
        {
            sourceProps[p.Name].SetValue(o, p.GetValue(values));
        }
    }
}

并像这样使用它:

person.With(new {Id = 1, Name = "Someone", BirthDate = DateTime.Now});

但是请注意,您依赖类型描述(或选择反射),并且只能在运行时发现属性名称中的错误。

答案 5 :(得分:1)

您可以使用Reflection(在类代码中添加using System.Reflection;)并将适当的方法添加到myClass

    public void SetProperties(params object[] args)
    {
        for (int i = 0; i < args.Count(); i += 2)
        {
            PropertyInfo myProp = this.GetType().GetProperty(args[i].ToString());
            myProp.SetValue(this, args[i + 1]);
        }
    }
您可以在代码中使用的

如下:

targetInstance.SetProperties("score", 1, "name", "John", "isAlive", true);

targetInstance.SetProperties("isAlive", true, "score", 1);

targetInstance.SetProperties("name", "John", "isAlive", true);

以此类推...

您可能希望使用Try / Catch块增强SetProperties(),以检查拼写错误的属性名称或值类型