通过将新对象分配给子实例来更新子对象

时间:2012-03-04 18:50:11

标签: c# entity-framework

这应该是一个基本的C#问题。假设我有一个 Person 类,其中包含名为 Pets 的属性,该属性为 List<Pet>

如果我想要更新宠物,我可以将宠物作为变量并操纵其上的属性,但我似乎无法创建新的宠物对象并将其分配给现有的宠物对象。我得到“分配的值未在任何执行路径中使用”警告。我创建了一些非常简单的代码来概述这个问题。

在我的真实代码中,我希望能够使用新的子对象并替换现有对象。如果您可以通过下面的示例updatedCat告诉我如何做到这一点,我将非常感谢!

class Program
{
  static void Main(string[] args)
  {
    var program = new Program();
    program.RunMe();
  }

  public void RunMe()
  {
    var myPerson = new Person() { Name = "John Doe" };
    var dog = new Pet() { Type = "Dog", Name = "Woofie" };
    var cat = new Pet() { Type = "Cat", Name = "Chester" };
    myPerson.Pets.Add(dog);
    myPerson.Pets.Add(cat);
    Console.WriteLine("Initial Pet Status:");
    ListPets(myPerson);

    var currentDog = myPerson.Pets.SingleOrDefault(p => p.Type == "Dog");
    currentDog.Name = "Snoopie";
    Console.WriteLine("\r\nPet Status After Updating Dog Directly (name should be 'Snoopie'):");
    ListPets(myPerson);

    var updatedCat = new Pet() { Type = "Cat", Name = "Felix" };
    var currentCat = myPerson.Pets.SingleOrDefault(p => p.Type == "Cat");
    currentCat = updatedCat; 
    //Resharper shows "Value assigned is not used in any execution path" for the currentCat
    //and the current cat is never updated
    Console.WriteLine("\r\nPet Status After Trying to Update Cat by Assigning a New Cat to existing Cat (name should be 'Felix' but it's not):");
    ListPets(myPerson);

    Console.ReadLine();
  }

  public void ListPets(Person person)
  {
    foreach (var pet in person.Pets)
    {
      Console.WriteLine(string.Format("   {0} has a {1} named {2}", person.Name, pet.Type, pet.Name));
    }
  }
}

public class Person
{
  public string Name { get; set; }
  public List<Pet> Pets { get; set; }

  public Person()
  {
    Pets = new List<Pet>();
  }
}

public class Pet
{
  public string Type { get; set; }
  public string Name { get; set; }
}

编辑以将Id值添加到Pet并创建InsertOrUpdatePet方法 (注意:我删除了Console.Writeline命令以简洁)

class Program
{
  static void Main(string[] args)
  {
    var program = new Program();
    program.RunMe();
  }

  public void RunMe()
  {
    var myPerson = new Person() { Name = "John Doe" };
    var dog = new Pet() { Id = 1, Type = "Dog", Name = "Woofie" };
    var cat = new Pet() { Id = 2, Type = "Cat", Name = "Chester" };
    myPerson.Pets.Add(dog);
    myPerson.Pets.Add(cat);

    var updatedCat = new Pet() { Id = 2, Type = "Cat", Name = "Felix" };
    InsertOrUpdatePet(myPerson, updatedCat);

    var currentCat = myPerson.Pets.SingleOrDefault(p => p.Type == "Cat");
  }


  public void InsertOrUpdatePet(Person person, Pet pet)
  {
    var currentPet = person.Pets.SingleOrDefault(p => p.Id == pet.Id);
    if(currentPet == null)
    {
      person.Pets.Add(pet);
    }
    else
    {
      currentPet = pet; // This doesn't work
      person.Pets.SingleOrDefault(p => p.Id == pet.Id) = pet; //This throws an error 
    }
  }

}

public class Person
{
  public string Name { get; set; }
  public List<Pet> Pets { get; set; }

  public Person()
  {
    Pets = new List<Pet>();
  }
}

public class Pet
{
  public int Id { get; set; }
  public string Type { get; set; }
  public string Name { get; set; }
}

2 个答案:

答案 0 :(得分:1)

您需要移除要替换的宠物并添加新宠物。

另外,你可以说

person.Pets[index] = new Pet() { Type = "Cat", Name = "Felix" };

其中index是您要替换的Pet的索引。

您不理解的是,宠物列表仅仅是对宠物实例的引用列表。

获取对这些Pet实例之一的引用并将其存储在变量中并为新的Pet实例分配引用不会更改List中任何引用所引用的位置。当然不是,你还没有修改过列表。这就是为什么要么必须删除要替换的元素,添加新元素,要么直接将新实例的引用分配给要替换的元素。

答案 1 :(得分:1)

这取决于你想在概念上做什么。如果你想说这个人摆脱了老猫并且现在有了一只新猫,你应该这样做:去除旧猫然后新猫:

var updatedCat = new Pet() { Type = "Cat", Name = "Felix" };
var currentCat = myPerson.Pets.SingleOrDefault(p => p.Type == "Cat");
myPerson.Remove(currentCat);
myPerson.Add(updatedCat);

另一方面,如果这个人仍然拥有相同的猫,但猫被重命名,你应该重命名旧猫,就像你对狗一样:

var currentCat = myPerson.Pets.SingleOrDefault(p => p.Type == "Cat");
currentCat.Name = "Felix";

您的代码不起作用,因为currentCat是引用cat的东西,而不是列表中的位置。如果你想用某种方式来表示列表中的位置,你可以使用索引到列表中,就像Jason建议的那样。