82

다음 클래스를 예로 들어 보겠습니다.

class Sometype
{
    int someValue;

    public Sometype(int someValue)
    {
        this.someValue = someValue;
    }
}

그런 다음 리플렉션을 사용하여이 유형의 인스턴스를 만들고 싶습니다.

Type t = typeof(Sometype);
object o = Activator.CreateInstance(t);

그러나 이것은 정상적으로 작동합니다.SomeType매개 변수없는 생성자를 정의하지 않았습니다.Activator.CreateInstance형식의 예외를 throw합니다.MissingMethodException메시지 "이 객체에 대해 정의 된 매개 변수없는 생성자가 없습니다."이 유형의 인스턴스를 생성하는 또 다른 방법이 있을까요? 내 모든 클래스에 매개 변수없는 생성자를 추가하는 것은 다소 불편할 것입니다.


  • FormatterServices.GetUninitializedObject초기화되지 않은 문자열을 만들 수 없습니다. 예외가 발생할 수 있습니다.System.ArgumentException: Uninitialized Strings cannot be created.이를 명심하십시오. - Bartosz Pierzchlewicz
  • 머리를 주셔서 감사합니다. 그러나 문자열과 기본 유형을 별도로 처리하고 있습니다. - Aistina

4 답변


122

원래이 답변을 올렸습니다.이리, 그러나 이것은 똑같은 질문이 아니기 때문에 재발행입니다. 그러나 같은 대답을 가지고 있습니다 :

FormatterServices.GetUninitializedObject()생성자를 호출하지 않고 인스턴스를 만듭니다. 나는이 수업을반사기일부 핵심 .NET 직렬화 클래스를 파고들 수 있습니다.

아래의 샘플 코드를 사용하여 테스트 한 결과 훌륭한 것으로 보입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;

namespace NoConstructorThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass)); //does not call ctor
            myClass.One = 1;
            Console.WriteLine(myClass.One); //write "1"
            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public MyClass()
        {
            Console.WriteLine("MyClass ctor called.");
        }

        public int One
        {
            get;
            set;
        }
    }
}



71

CreateInstance 메서드의 다음 오버로드를 사용합니다.

public static Object CreateInstance(
    Type type,
    params Object[] args
)

지정된 인스턴스를 작성합니다.   가장 잘 생성자를 사용하여 유형을 지정하십시오.   지정된 매개 변수와 일치합니다.

만나다:http://msdn.microsoft.com/en-us/library/wcxyzt4d.aspx


  • 이 솔루션은 문제를 단순화합니다. 내 유형을 모르는 경우 " ;, "이 유형 변수에 유형의 개체 만 생성 "이라고 말하면 어떻게됩니까? - kamii

18

내가벤치마킹 된의 성능(T)FormatterServices.GetUninitializedObject(typeof(T))그것은 더 느렸다. 동시에 컴파일 된 표현식은 기본 생성자가있는 유형에서만 작동하지만 속도가 크게 향상됩니다. 나는 하이브리드 접근 방식을 취했다 :

public static class New<T>
{
    public static readonly Func<T> Instance = Creator();

    static Func<T> Creator()
    {
        Type t = typeof(T);
        if (t == typeof(string))
            return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();

        if (t.HasDefaultConstructor())
            return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();

        return () => (T)FormatterServices.GetUninitializedObject(t);
    }
}

public static bool HasDefaultConstructor(this Type t)
{
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}

이는 create 표현식이 효과적으로 캐시되고 유형이 처음로드 될 때만 패널티가 발생 함을 의미합니다. 효율적인 방식으로 값 유형을 처리합니다.

불러라:

MyType me = New<MyType>.Instance();

유의 사항(T)FormatterServices.GetUninitializedObject(t)문자열에 대해 실패합니다. 따라서 빈 문자열을 반환하기 위해 string에 대한 특수 처리가 제 위치에 있습니다.


  • 다른 사람의 코드 한 줄을 보면 하루를 절약 할 수있는 것이 이상합니다. 감사합니다! 성능상의 이유로 게시물이 나에게 전송되었고 트릭이 완료되었습니다. FormatterServices 및 Activator 클래스는 컴파일 된 표현식에 비해 실적이 저조합니다. - jmodrak
  • @nawfal 문자열에 대한 특수 처리에 관해서는이 특별한 처리가없는 문자열에 대해서는 실패한다는 것을 알고 있지만 단지 알고 싶습니다.모든다른 유형? - Sнаđошƒаӽ
  • @ Sнаđошƒаӽ 불행히도 아니오. 주어진 예제는 베어 본 (barebones)이며 .NET에는 여러 유형의 유형이 있습니다. 예 : 당신이 델리게이트 타입을 전달한다면 어떻게 그것을 인스턴스로 줄 것인가? 그렇지 않으면 생성자가 당신이 그것에 대해 할 수있는 일을 던지면? 여러 가지 방법으로 처리 할 수 있습니다. 내 라이브러리에서 더 많은 시나리오를 처리하기 위해 업데이트 된 이후로 대답했습니다. 지금은 어디에도 게시되지 않습니다. - nawfal

4

좋은 답변이지만 닷넷 컴팩트 프레임 워크에서는 사용할 수 없습니다. CF.Net에서 작동하는 솔루션은 다음과 같습니다.

class Test
{
    int _myInt;

    public Test(int myInt)
    {
        _myInt = myInt;
    }

    public override string ToString()
    {
        return "My int = " + _myInt.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var ctor = typeof(Test).GetConstructor(new Type[] { typeof(int) });
        var obj = ctor.Invoke(new object[] { 10 });
        Console.WriteLine(obj);
    }
}


  • 이것이 기본이 아닌 생성자를 호출하는 방법입니다. 생성자를 호출하지 않고도 객체를 만들고 싶지는 않습니다. - Rory MacLeod
  • 커스텀 시리얼 라이저를 작성하는 경우 생성자를 호출하지 않고 객체를 만들 수 있습니다. - Autodidact
  • 그렇다면 정확한 사용 사례 시나리오는 다음과 같습니다. :) - Aistina
  • @Aistina 아마도이 정보를 질문에 추가 할 수 있습니까? 대부분의 사람들은 자신의 담당자를 부르지 않고 객체를 만드는 것에 반대 할 것이며, 그것에 대해 논할 시간이 필요 하겠지만, 유스 케이스는 실제로 그것을 정당화하므로 질문 자체와 매우 관련이 있다고 생각합니다. - julealgon

연결된 질문


관련된 질문

최근 질문