2012-03-04 54 views
0

這應該是一個基本的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添加到寵物和創建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; } 
} 
+1

後者不起作用。 – jason 2012-03-04 18:56:32

+0

看起來你還不瞭解對象和對象引用之間的區別。你可能想對此做一些研究。 – usr 2012-03-04 19:00:15

回答

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的東西,引用貓,而不是列表中的位置。正如Jason所建議的,如果你想用某種方式來表示列表中的位置,那麼你可以使用索引到列表中。

+0

謝謝Svick。正如我在下面向傑森陳述的那樣,並在我的編輯中顯示的,如果我創建UpdateOrInsert方法並將更新後的寵物參數作爲變量進入該方法,那麼如何更新Person.Pets集合?由於我正在使用實體框架並且正在跟蹤上下文,因此我希望保持該對象與剛剛更新的屬性相同(因爲它由EF跟蹤)。 – bigmac 2012-03-04 19:22:08

1

你需要刪除的寵物你想替換並添加一個新的寵物。

Alteratively,你可以說

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

其中index是要更換寵物的索引。

你不明白的是,寵物列表僅僅是一個對寵物實例的引用列表。

獲取對這些Pet實例之一的引用並將其存儲在一個變量中,併爲Pet的新實例分配一個引用不會改變List中引用的任何引用。當然不是,你還沒有修改列表。這就是爲什麼您必須移除要替換的元素,並添加新元素,或直接將新實例的引用分配給要替換的元素。

+0

謝謝賈森......這開始有道理,但我編輯了我的原始問題,以更密切地顯示我在我的真實代碼中所做的事情。我想在我的業務層中有一個可以更新「寵物」的InsertOrUpdate方法(或者如果基於唯一的Id值不存在,則添加一個新的方法)。我在更新中遇到困惑。如果更新的寵物參數作爲變量進入方法,我如何更新Person.Pets集合?那有意義嗎? – bigmac 2012-03-04 19:20:14