2014-10-30 2 views
6

저는 얼마 동안 PHP 프로그래머입니다. 이틀 전, 나는 그들이 ASP.NET에서 할 결심을 줬던 취업 면접에 갔다 (C#). 나는 영향력의 PHP 영역에서 벗어나 나에게 도전할만한 적절한 언어를 배우고 싶다. 그래서 질문이 있습니다C# - Object Creation

런타임에 모든 인스턴스를 인스턴스화해야합니까? PHP에서, 나는 이런 식으로 할 수 있습니다 ...

class SomeObject {} 

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

저는 C#에서 그렇게 할 수 없습니다. 아마도 컴파일 된 언어 일 것입니다. C#에서는 개체를 인스턴스화하는 팩터 리 패턴을 만들어야합니다. 또한 그 공장에서 10 개의 객체를 인스턴스화해야한다면 1if 진술이 추악 할 것입니다.

Activer 객체가있는 Activator::createInstance() 메서드가 있는데 제대로 작동하지 않습니다. 또한 Reflection이 있지만 두 가지 모두 (내가 알고있는 것처럼) 성능에 영향을 미칩니다.

그래서 동적으로 개체를 만드는 방법이 있습니까? 아니면 C#에서 내 프로그램에서 사용할 모든 개체를 즉시 만들 수 있습니까? 정말 유혹입니까?

편집

이 좋아, 그래서 내가 5 가지 occassions에 사용됩니다 5 개체가 있다고 가정 해 봅시다. 나는 프로그램을 실행하고, 프로그램은 그 객체 중 하나가 필요하다는 것을 평가하고 그것을 인스턴스화한다. 나머지 네 개는 결코 인스턴스화되지 않습니다. 나는 프로그램을 닫는다.

두 번째로 다른 매개 변수를 사용하여 프로그램을 실행하고 5 개의 개체 중 2 개가 만들어지고 다른 세 개는 결코 존재하지 않습니다.

이것은 PHP로 쉽습니다. 액티베이터와 다른 도구를 제쳐두어 보겠습니다. C#에서 5 가지 객체를 모두 만드는 것이 좋을지 모르지만 그 중 하나만 사용됩니다.

+3

PHP를 모르지만 C#에서는 개체를 만들고 동시에 초기화 할 수 있습니다. 팩토리 또는 Activator 객체를 사용할 필요가 없습니다. 간단히 SomeObject someObj = new SomeObject();가됩니다. – Tim

+10

.NET에서 이와 같이 동적으로 객체를 생성 할 수 있지만 구문뿐만 아니라 전체 언어, 런타임, 플랫폼을 배워야합니다. 내 말은 당신이 C#에서 PHP로했던 것처럼 프로그래밍을 유지하려고한다면, 당신은 매우 나쁜 경험을하게 될 것입니다. –

+0

"런타임에 모든 인스턴스를 인스턴스화해야합니까?" 음, 아니, 제 말은, 컴파일 시간이나 커피 타임을 인스턴스화하지 않는다는 것입니다.하지만 그 중 하나를 인스턴스화하지 않아도됩니다. (그리고 당신이 원하지 않는다면 확실히 반성을 사용할 필요가 없습니다.) – atlaste

답변

4

나는 당신의 질문이 잘못 가지고 있는지 알고 있지만, C 번호에 지정된 클래스 SomeObject의 객체를 생성하면 다음처럼 간단하지 않습니다.같은 다음

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); 

주 중 하나는 객체를 instanciating의 Activator -Class를 사용하는 것은 대부분의 경우 필요하지 않다고. 첫 번째 예제는 컴파일 타임에 클래스의 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 

    [...] 

} 

처럼 백업 필드 properies를 사용하여 문제를 해결할 수 있습니다, 난 당신이 제대로 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

네, 고마워요. 이 질문에 대한 답은 모두 PHP에서 생각하기를 멈추고 C#과 같은 생각을 시작해야한다고 기본적으로 말했습니다. 내 말은, 나는 약 1 시간 반 동안 C#을 배웠고 경험은 시간과 함께 왔지, 그렇지? –

+2

왜'게으른'> 아닌가요? –

+0

저는 기사에 크기가있는 질문을했습니다. "게으른 방법은 C#으로 개체를 인스턴스화 할 수 있습니까?" 그리고 그것은 그것 일 것입니다. 내 편이 아니라고! 고맙습니다. –

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에는 자신의 문제가 일부 있음을 유의하십시오. SomeObjectSystem 네임 스페이스에있는 경우 위 코드가 작동합니다. 네임 스페이스, 클래스 및 언젠가 어셈블리를 추가해야 할 수도 있습니다. 모두 AssemblyQualifiedName을 사용하는 것이 가장 안전합니다. 이 STH를 보여야 Activator -Class를 사용

var obj = new SomeObject(); 

:

+0

'SomeObject' 클래스가'ConsoleApplication1'과 같은 일부 네임 스페이스 내에서 범위가 지정되면 초보자에게 명확하지 않습니다. GetType ("ConsoleApplication1.SomeObject"); ' –

5

예, C#에서 개체를 동적으로 만들 수 있습니다. PHP처럼 쉽지는 않습니다.

발견 한대로 Activator입니다. 올바르게 사용할 때 제대로 작동합니다. :) 직접 반사도 있습니다 (Activator은 반사도를 기반으로합니다). 순진하게 사용하면 둘 다 느립니다.

Expression 유형을 사용하면 객체를 인스턴스화하기위한 논리를 캐시 할 수 있습니다. 처음에는 여전히 느리지 만 동일한 유형의 객체를 반복해서 만들려면이 접근법이 잘 작동합니다 (그렇지 않은 경우 Activator을 통해 느리다는 사실은 중요하지 않습니다 :)).

그런데 대부분의 경우에는 예를 들어 동적으로 개체를 생성 할 필요가 없습니다. C#의 강력한 컴파일 타임 형식 확인은 피하지 말고 활용해야합니다. 형식이 컴파일 타임에 이미 알려져있는 개체를 인스턴스화하는 코드를 작성하는 것이 가장 효율적이며 형식에 가장 안전합니다.

동적 동작이 필요한 비교적 적은 시간 동안 가능합니다.

1

C#에서 클래스의 인스턴스를 만드는 데는 몇 가지 방법이 있습니다.

일반적인 방법은 단순히 new을 사용하는 것입니다 : 예, Activator.Createinstance() 작품에 대한 자신의 이름을 기반으로 동적으로 생성하는 객체의 경우

MyType myInstance = new MyType(); 

,하지만 당신은 그 클래스가 정의 된 어셈블리를 알고 있어야 제대로 할 수 있도록 그 인스턴스를 만듭니다.

그러나 아직 시작한 사람이라면 특히이 문제에 익숙해 질 필요가 없습니다.
C#은 정적 형식의 언어입니다. 즉, 컴파일 중에 형식 확인이 수행됩니다.

그 외에도 IDE의 Visual Studio가 프로젝트의 파일을 스캔하고 코드에 입력하는 각 멤버의 유형을 알 수 있으므로 대단히 도움이된다고 생각하십시오.

정적 유형의 언어는 순전히 동적 인 언어에서 발생하는 정확한 종류의 문제를 피하는 데 유용합니다. 즉, 사용자가 선언문에 명시해야하는 비용을 부담해야합니다 (C#은 var 키워드는 일반적으로 필요한 자세한 정보를 피하는 데 많은 도움이됩니다.)

전체 요점은 응용 프로그램에서 필요한 모든 유형을 선언했는지 확인하는 것입니다.

다른 클래스의 데이터를 받아들이려면 특정 클래스 멤버가 필요하면 inheritance을 사용하여 다른 클래스에서 일부 동작을 상속하거나 기본 클래스를 만들어 Interfaces을 사용하여 일반 멤버를 다양한 형식으로 설명 할 수 있습니다. 각각은 advantages and drawbacks입니다.

C#으로 도발적이라면 실험을 해본 후 LINQpad을 권하고 싶습니다. 학습하는 동안 실험하는 데 도움이 될 수 있습니다.

나는 canonical이 아닌 다른 것들로부터 멀리 떨어져있을 것이다 : 당신이 런타임 물건을하기에는 너무 깊이 들어가기 전에 관용적 인 C#을 먼저 이해하라.

하나의 영역을 탐색 할 수 있지만 dynamic 유형입니다. 진정으로 역동적 인 언어에서 기대하는 것만 큼 유연하지는 않지만 유형 불확실성을 처리 할 수있는 방법입니다.
성능상의 단점이 있지만 Visual Studio에서 Intellisense를 활용하고 IDE 및 컴파일러에서 제공 할 수있는 일반적인 유형 확인의 이점을 얻으려면 피해야합니다.

+0

나는이 질문을저기서 물어 보았습니다. 그래서 나는 당신에게 그것을 복사/붙여 넣을 것입니다. 나는 문자열의 변화하는 값에 생성 될 5 개의 객체 풀에서 1 개의 객체를 가지고 있다고 가정 해 봅시다. 그 말은 원하는 if 객체를 생성하는 if 문 (또는 case 또는 기타)을 5 개 가질 것입니다. 그것은 바람직한 것이고 C#에서는 일반적인 관행입니까? –