簡體   English   中英

修改作為參數傳遞到修改類的對象的正確方法

[英]The correct way to modify an object that is being passed as a parameter into the modifying class

以下2個建議修改由接受該對象作為參數的類修改的對象的屬性的最佳方法是什么?

  1. 讓類處理對象並返回一個值,然后將該值賦給對象

要么。

  1. 使用ref關鍵字傳遞對象,並讓類修改對象而不實際返回任何內容。

例如,我有一個具有名字和姓氏的Person對象以及2種創建全名的方法。

哪種方式最好?

public static void Main()
{
    Person a = new Person {  FirstName = "John", LastName = "Smith" };
    Person b = new Person { FirstName = "John", LastName = "Smith" };

    NameProcesser np = new NameProcesser();

    // Example A
    a.FullName = np.CreateFullNameA(a);

    // Example B
    np.CreateFullNameB(ref b);
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName { get; set; }
}


public class NameProcesser
{
    public string CreateFullNameA(Person person)
    {
        return person.FirstName + " " + person.LastName;
    }

    public void CreateFullNameB(ref Person person)
    {
        person.FullName = person.FirstName + " " + person.LastName;
    }
}

你不需要ref 只需修改方法中的對象即可。

當引用類型作為參數傳遞時,它將“通過引用”傳遞,而不是通過值傳遞。 因此,當您修改它時,您實際上正在修改原始對象。 如果要傳遞值類型(如int則只需要ref

我在引號中說“引用”,因為實際發生的是原始對象的內部“指針”正在通過傳遞。

首先要做的事情

你提到ref的事實表明你錯過了一個基本概念; 也就是說,根據定義,可以訪問對象引用的代碼可以訪問實際對象。

您可以使用ref參數的唯一可能的使用場景是,您希望將該引用設置為某個其他對象,或者為null

如果你不使用ref (或者甚至是out for this,請看這里的區別)你實際上是通過值傳遞你的參數,這意味着它的副本被創建了。

這意味着兩件事,取決於參數是值類型 (如int,long,float等)還是引用類型 (引用任何類的實例)。

如果參數是值類型,則將創建其副本。 然后,您的方法可以執行任何想要的操作,因為副本僅限於該方法的范圍。

但是,如果參數是引用類型(就像您的Person那樣),則僅復制引用本身:基礎對象是相同的。 這是最大的不同之處。 但請記住,方法中可用的引用仍然是原始引用的副本,這意味着您可以將其設置為null ,將其設置為另一個對象,簡而言之,使用它執行任何您喜歡的操作:一旦方法返回,該引用將消失,原始引用將保持不變。

話雖如此

正如其他人告訴你的那樣,真的沒有必要使用ref

而且,只要你處理諸如連接名字和姓氏之類的瑣碎案例,我就會讓對象本身這樣做(就像Slapout一樣)。

如果出現這種需要,總會有時間將責任分開。

還要考慮為這樣一個瑣碎的任務設一個單獨的類也可能被認為是違反直覺的。 說這是手頭的代碼:

var p = new Person() { FirstName = "John", LastName = "Smith"} ;

Console.WriteLine(p.FullName);

當我這樣做時,我完全希望FullName始終返回一些有意義的東西(即“John Smith”)。

相反,如果我忘記(並且我會 )調用CreateFullName ,那么會發生什么?

如果您確實需要將給定的關注點移動到單獨的類中,請將其隱藏在屬性的get方法中。

這樣,人們就不需要知道你所寫的類的基礎,而且它仍然是可測試的。

兩者都沒有 - 你不需要'參考' - 只需使用:

public void CreateFullNameB(Person person) 
{ 
    person.FullName = person.FirstName + " " + person.LastName; 
} 

首先,將該方法分成另一個類的唯一原因是該方法是否具有數據庫或網絡訪問等依賴關系。 否則,該簡單方法應該是Person類的屬性。

另外,只有當對象數據在該方法中被廣泛使用時才將整個對象傳遞給方法。 否則最好將FirstName和LastName作為參數傳遞並返回結果。

不需要使用ref修飾符傳遞類來修改其內容。 ref僅在方法需要賦值參數以及對新實例的引用時才需要。

在示例中,您描述了如果從兩個選項中選擇返回值更好,因為它減少了耦合並將邏輯與數據表示分開。 但是,如果可以更新實體的少數屬性,那么傳遞對象會更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM