2015-10-30 39 views
0

我來自JavaScript並試圖更好地理解在C#中使用對象的方式。我有一些簡單的代碼:訪問對象屬性的更優雅或有效的方式?

class Program 
{ 
    static void Main(string[] args) 
    { 
     MyClass firstObj = new MyClass(); 
     firstObj.Number = 6; 
     Console.WriteLine(firstObj.Number); 

     object secondObj = doResults(); 
     string getString = secondObj.GetType().GetProperty("resultsString").GetValue(secondObj).ToString(); 
     Console.WriteLine(getString); 

     Console.ReadLine(); 
    } 

    public static object doResults() 
    { 
     ResultsObj newResults = new ResultsObj(); 
     newResults.resultsString = "Here is my string"; 

     return newResults; 
    } 

} 

public class MyClass 
{ 
    public int Number { get; set; } 
} 

public class ResultsObj 
{ 
    public string resultsString { get; set; } 
} 

在main()的第一部分,我創建一個對象,添加屬性,設置一個值,然後訪問並顯示該值。它的所有非常簡單。

在Main()的第二部分,我調用了doResults()方法,該方法創建一個字符串屬性的對象。

我的問題是這樣的一行:

string getString = secondObj.GetType().GetProperty("resultsString").GetValue(secondObj).ToString(); 

如此看來涉及到我。這真的是訪問返回對象的屬性的正確/最有效的方式嗎?

+4

爲什麼返回'object'而不是'ResultsObj'?你在這裏失去了所有類型的安全。 – DavidG

+0

也許這是問題的根源。就像我剛纔說的,來自JavaScript,我習慣於把對象放在一邊而沒有什麼複雜性,所以我的C#方法可能是錯誤的。 –

+0

在你的情況下,一個簡單的轉換就可以工作:'((MyClass)ResultsObj).resultsString' –

回答

9

C#和JavaScript之間的根本區別在於C#是一種強類型語言。在您沒有「添加屬性」的main方法中,您設置了現有屬性的值。你有這麼多麻煩的原因是你的參考變量是不正確的類型

A 類型是對象實例的屬性和方法(藍圖)的集合。這與JavaScript類似,只不過在JavaScript中,您可以在運行時添加屬性和方法,而在C#中則無法添加屬性和方法,但只限於編寫代碼時可用的內容(ExpandoObject是更高級的概念除外)。編譯器將只允許您訪問用於生成該引用的變量類型定義的屬性和方法。當您從方法中返回object時,您說「此方法的調用者只能訪問object的屬性和方法」。

所以基本上你需要決定你想讓消費者能夠訪問的屬性和方法(即類型)。在這種情況下,您的方法會創建ResultsObj的實例並將其返回,因此返回類型應定義爲ResultsObj。現在

public static ResultsObj doResults() 
{ 
    ResultsObj newResults = new ResultsObj(); 
    newResults.resultsString = "Here is my string"; 

    return newResults; 
} 

調用代碼知道它是什麼取回是ResultsObj可以可以訪問的屬性和類型的方法。

ResultsObj secondObj = doResults(); 
Console.WriteLine(secondObj.resultsString); 

這一切都歸結到類型。重申一下,編譯器只允許您訪問由引用變量定義的類型的屬性和方法。

順便說一句,你還可以寫代碼的第二塊爲:

var secondObj = doResults(); 
Console.WriteLine(secondObj.resultsString); 

這似乎令人困惑,從一個JavaScript的背景特別是即將在那裏var意味着不同的東西。在這種情況下,C#正在做隱式打字。因爲方法doResults()被定義爲返回ResultsObj,所以變量secondObj被隱式鍵入。如果您試圖編寫下面的代碼,它不會編譯,因爲隱式鍵入已經決定secondObjResultObj,並且您不能將一個數字分配給ResultsObj類型的變量。

var secondObj = doResults(); 
secondObj = 1; // This would cause a compiler error 
+0

...如果你想實際添加屬性,你應該看看'dynamic'或['ExpandoObject'](http: //stackoverflow.com/q/1653046/11683)。 – GSerg

+0

你能提供一些示例代碼嗎? –

+0

雖然var是一個選項,並且可以工作,但我發現最好使用實際的對象類型(在本例中爲ResultsObj)而不是var。這使得代碼更容易被稍後進入的人或者最初沒有寫入的人讀取。否則,他們必須去doResults()定義來找出它返回的內容。 – Wolfie

5

不,使用反射確實不是最有效的方法。但更重要的是,它也不是最可讀的方式。編寫編譯時類型安全的代碼。

,而不是返回Object,你應該返回正確的類型ResultsObj

public static ResultsObj doResults() 
{ 
    ResultsObj newResults = new ResultsObj(); 
    newResults.resultsString = "Here is my string"; 

    return newResults; 
} 

那麼它很容易,可讀性強,安全高效:

ResultsObj secondObj = doResults(); 
string getString = secondObj.resultsString; 

如果你不能改變的類型和你必須使用Object你可以cast它正確的類型:

object secondObj = doResults(); 
ResultsObj resultObj = (ResultsObj) secondObj; 
string getString = resultObj.resultsString; 
2

變化:

public static object doResults() 

到:

public static ResultsObj doResults() 

則:

string getString = secondObj.resultsString; 
3

在C#中我們只要你能式安全所以用它。所以不是返回object,返回你所使用的類型,例如:

public static ResultsObj doResults() 
{ 
    ResultsObj newResults = new ResultsObj(); 
    newResults.resultsString = "Here is my string"; 

    return newResults; 
} 

然後你使用這樣的:

ResultsObj secondObj = doResults(); 
secondObj.resultsString = "blah"; 

另一種方法(我只在這裏提到,因爲它可以有用某些情況下,所以不要這樣默認的代碼)是使用類型dynamic。這將刪除所有類型檢查,但意味着你必須要小心你的代碼:

dynamic secondObj = doResults(); 
secondObj.resultsString = "blah"; //this will work 
secondObj.NonExistantProperty = "blah"; //this will compile but fail at runtime 
+0

可能值得注意的是'動態'也意味着Intellisense將無法正常工作,所以很容易發生打印錯誤和外殼問題,直到運行時纔會出現。 –

3

1.Return一個ResultsObj,而不僅僅是一個object

public static ResultsObj doResults() 
{ 
    ResultsObj newResults = new ResultsObj(); 
    newResults.resultsString = "Here is my string"; 

    return newResults; 
} 

2.call用正確的左側方法手側:

ResultsObj res = doResults(); 
Console.Write(res.resultsString); 

PS:左手側可以是VAR(編譯器特性)等在JS:

var res = doResults(); 
Console.Write(res.resultsString); 
相關問題