2014-10-30 163 views
6

我是一個PHP程序員一段時間。前兩天,我去了一個求職面試,他們給了我一個ASP.NET(C#)的分配。我真的很想脫離php的勢力範圍,並學習一種體面的語言來挑戰我。所以,我有一個問題C# - 對象創建

是否所有實例都必須在運行時實例化?在PHP中,我可以做這樣的事情......

class SomeObject {} 

$objString = "SomeObject"; 
$objInstance = new $objString(); 

我不能這樣做,在C#中,大概怎麼一回事,因爲它是一個編譯語言。在C#中,我需要創建一個工廠模式來實例化對象。這也意味着,如果我必須在該工廠中實例化10個對象,那麼將會有10個if陳述是醜陋的。

我發現Activator對象的方法是Activator::createInstance(),但我無法讓它工作。也有反思,但這兩個(如我所知)是一個性能影響。所以,有沒有辦法動態創建對象,或者它可能是在C#中,我可以立即創建我的程序將使用的所有對象,這真的很誘人?

編輯

好了,讓我們說,我有一個在5個不同的occassions使用5對象。我運行程序,程序評估它需要這些對象之一併實例化它。其他四個從未實例化。我關閉了該程序。

第二次,我用不同的參數運行程序,其中兩個5個對象被創建,其他三個從未存在。

這在PHP中很容易。讓我們把Activator和其他工具放在一邊,當我知道可能只有其中一個會被使用時,在C#世界中創建所有5個對象是否是一個好習慣?

+3

我不知道PHP,但在C#中,您可以創建一個對象並同時進行初始化。你不需要使用工廠或Activator對象 - 只需要'SomeObject someObj = new SomeObject();'就可以。 – Tim 2014-10-30 07:42:34

+10

在.NET中動態構建對象是可能的,但您應該瞭解整個語言,運行時,平臺,而不僅僅是語法。我的意思是,如果您嘗試像在C#中使用PHP那樣繼續編程,那麼您將會遇到一個非常糟糕的體驗。 – 2014-10-30 07:52:17

+0

「是否所有實例都必須在運行時實例化?」。那麼不,我的意思是,如果你的意思是它們沒有實例化編譯時或咖啡時間......但是你沒有實例化它們中的任何一個。 (如果你不想,你肯定不需要使用反射)。 – atlaste 2014-10-30 07:54:47

回答

4

我不知道如果我得到你的問題錯了,但在C#創建給出SomeObject類的對象是那麼容易,因爲以下幾點:

var obj = new SomeObject(); 

使用Activator -Class看起來應該做某事。像下面

var obj2 = Activator.CreateInstance(typeof(SomeObject)); 
var obj3 = Activator.CreateInstance<SomeObject>();` 

var someObjType = Type.GetType("SomeObject"); // if you have to use a string 
var obj4 = Activator.CreateInstance(someObjType); 

注意的一個,使用Activator -Class的instanciating對象是不是在大多數情況下,必要的。第一個例子是在編譯時知道類的Type的標準方式。

UPDATE

關於您的更新,因爲我不知道的細節是什麼在我腦海中是懶惰instanciation。由於一切,包括你的應用程序的入口點在C#中的對象,你可以用備份領域解決使用性的判定問題就像下面這個例子

class Program 
{ 
    // backing fields 
    private SomeObject obj1; 
    private SomeObject obj2; 
    private SomeObject obj3; 
    private SomeObject obj4; 
    private SomeObject obj5; 

    // this way, obj1 only gets instanciated when needed 
    public SomeObject Obj1 
    { 
     get 
     { 
      if (obj1 == null) 
      { 
       obj1 = new SomeObject(); 
      } 
      return obj1; 
     } 
    } 

    // same for the other objects 

    [...] 

} 

我你關心你的對象的內存使用情況,我建議你瞭解如何正確實現IDisposable

更新2

要通過@瘋狂的魔法師提供意見建議的可能性,你可以使用Lazy -Class備份領域,其需要付出一些努力,效果與之前的更新完全相同。

class Program 
{ 
    // Lazy backing fields 
    private Lazy<SomeObject> obj1 = new Lazy<SomeObject>(); 
    private Lazy<SomeObject> obj2 = new Lazy<SomeObject>(); 
    private Lazy<SomeObject> obj3 = new Lazy<SomeObject>(); 
    private Lazy<SomeObject> obj4 = new Lazy<SomeObject>(); 
    private Lazy<SomeObject> obj5 = new Lazy<SomeObject>(); 

    // this way, obj1 only gets instanciated when needed 
    public SomeObject Obj1 
    { 
     get { return obj1.Value; } 
    } 

    // same for the other objects 

    [...] 

} 
+0

是的,謝謝。在這個問題上的所有答案basiclly告訴我,我應該停止在PHP思考,並開始思考像C#。我的意思是,我一直在學習C#大約一天半的時間,並且體驗隨着時間而來,對吧? – 2014-10-30 08:13:20

+2

爲什麼不'懶惰<>'? – 2014-10-30 08:15:15

+0

我寫了一篇文章大小的問題,當我可以問「有沒有辦法在C#中實例化一個對象?」那就是它。在我身邊不聰明!非常感謝你。 – 2014-10-30 08:22:23

2

因此,PHP代碼...你選擇哪個類實例化它的名稱作爲一個字符串?

您需要先查找類型,然後使用Activator對其進行實例化。

Type classType = Type.GetType("SomeObject"); 
object instance = Activator.CreateInstance(classType); 

你可以看一下它的構造函數和調用,而不是使用反射,看起來更像是這個

Type classType = Type.GetType("SomeObject"); 
var ctorInfo = classType.GetConstructor(Type.EmptyTypes); 
object instance = ctorInfo.Invoke(new object[] {}); 

,你可以緩存構造爲代表,其消除了來自仰視的性能損失東西#

請注意,Type.GetType有它自己的一些問題。如果SomeObject位於System名稱空間中,則上述代碼將可用。您可能需要添加命名空間,類和某個時間程序集。總之,使用AssemblyQualifiedName是最安全的。

+0

對於初學者來說,如果'SomeObject'類在像ConsoleApplication1這樣的名稱空間範圍內,它應該被明確地顯示:'GetType (「ConsoleApplication1.SomeObject」);' – 2014-10-30 07:59:12

5

是的,你可以在C#中動態創建對象。但不像在PHP中那麼容易。

如您所見,有Activator。當你正確使用它時它工作正常。 :)也有直接反映(Activator也是基於反思)。天真地使用時都很慢。

使用Expression類型,可以緩存實例化對象的邏輯。它仍然是第一次,但如果你期望重複創建相同類型的對象,這種方法效果很好(如果你不這樣做,那麼它通過Activator緩慢的事實並不重要:))。

也就是說,大多數情況下,您不需要像在您的示例中那樣動態創建對象。 C#中強大的編譯時類型檢查應該被利用,而不是被避開。編寫實例化在編譯時已知類型的對象的代碼是最有效的,也是最安全的類型。

對於那些你確實需要動態行爲的人來說,這是可能的。

1

有幾種方法可以在C#中創建一個類的實例。

的常用方法就是使用new

MyType myInstance = new MyType(); 

用於動態創建對象,根據他們的情況下,Activator.Createinstance()作品的名字,但你必須知道那類中定義的組件,以便正確創建該實例。

但是,特別是如果你剛剛開始,我不打擾進入這一點呢。
C#是一種靜態類型的語言,這意味着在編譯過程中類型的分辨率。

最重要的是,考慮到IDE,Visual Studio可以極大地幫助您,因爲它可以掃描項目中的文件,並知道您在代碼中輸入的每個成員的類型。

靜態類型語言有助於避免純動態語言中出現的確切類型的問題:它們會迫使您保持一致,但要求您在聲明中明確表示(儘管C#與var關鍵字可以幫助您避免通常需要的冗長)。

因此,重點是確保您在應用程序中聲明所有需要的類型。

如果你需要一個特定的類成員從多個其他類接受數據,你可以使用inheritance,創建一個基類,其他人將繼承某些行爲,或使用Interfaces,共同成員描述爲多種類型。每個都有它的advantages and drawbacks

如果您正在涉足C#,只是嘗試一下,我建議您獲得LINQpad。它可以幫助你在學習的同時做實驗。

我也會遠離任何不規範的東西:在嘗試做運行時間的東西之前先深入瞭解慣用的C#。

您可以探索的一個領域是dynamic類型。它不如您期望的真正動態語言那樣靈活,但它是處理類型不確定性的一種方式。
儘管它有性能上的缺陷,但如果您想從Visual Studio中的Intellisense中受益並且希望從IDE和編譯器可以爲您提供的正常類型檢查中受益,應該避免使用它。

+0

我在那裏問了這個問題,所以我只是複製/粘貼給你。比方說,我有一個5個對象池中的1個對象,這些對象將在字符串的變化值上創建。這意味着我會有5個if語句(或者case或其他),然後創建所需的對象。這是可取的,並在C#中的正常做法? – 2014-10-30 08:09:34