C # Yeni T Oluştur ()


159

Aşağıdaki kodla ne yapmaya çalıştığımı (ancak başarısız olduğunu) görebilirsiniz:

protected T GetObject()
{
    return new T();
}

Herhangi bir yardım büyük mutluluk duyacağız.

DÜZENLE:

Bağlam aşağıdaki gibidir. Tüm denetleyicilerin türetilmesi için standartlaştırılmış yöntemlerle özel bir denetleyici sınıfıyla oynuyordum. Bu yüzden bağlamda, denetleyici türünde nesnenin yeni bir örneğini oluşturmam gerekiyordu. Yani yazarken, şöyle bir şeydi:

public class GenericController<T> : Controller
{
    ...

    protected T GetObject()
    {
        return (T)Activator.CreateInstance(ObjectType);
    }        

    public ActionResult Create()
    {
        var obj = GetObject()

        return View(obj);
    }

Ve bu yüzden burada yansımanın en kolay olduğuna karar verdim. Kesinlikle sorunun ilk ifadesi göz önüne alındığında, doğru olarak işaretlemek için en uygun cevabın yeni () kısıtlamasını kullanan cevap olduğunu kabul ediyorum. Bunu düzelttim.


27
Hayır, ne yapmaya çalıştığınızı göremiyorum. Bağlam, hata mesajı ve açıklama olmadan çalışan bir programın parçası olabilecek bir kod parçası görüyorum.
Ben Voigt

17
Hatalı cevap seçildiğinde nefret ediyorum!
David Heffernan

Yanıtlar:


409

Yeni Kısıtlamaya bir göz atın

public class MyClass<T> where T : new()
{
    protected T GetObject()
    {
        return new T();
    }
}

Tvarsayılan yapıcısı olmayan bir sınıf olabilir: bu durumda new T()geçersiz bir ifade olur. new()Kısıt söylüyor Tkılan bir varsayılan kurucu, sahip olmalıdır new T()yasal.

Aynı kısıtlamayı genel bir yönteme uygulayabilirsiniz:

public static T GetObject<T>() where T : new()
{
    return new T();
}

Parametreleri geçirmeniz gerekiyorsa:

protected T GetObject(params object[] args)
{
    return (T)Activator.CreateInstance(typeof(T), args);
}

2
Teşekkürler dostum - Bunu bugün öğrendiğime sevindim. Metodumun bağlamı göz önüne alındığında, yansıma çözümü için gittim. Şerefe!
Hanshan

8
@nulliusinverba - hmm ... soruda yönteminizin bağlamını göstermeniz güzel olurdu.
Alex Aza

1
@nulliusinverba - soruda parametrelere ihtiyacınız olduğunu göstermediniz.
Alex Aza

1
@Alex - Sorusunu okuduğumda parametreler istemediğini varsaydım: S Ancak sizin için yukarı oy verin :)
Phill

Yeni (parametreler) kısıtlaması gibi bir şey kullanmak mümkün müdür?
Louis Rhys


29

Başka bir yol da yansımayı kullanmaktır:

protected T GetObject<T>(Type[] signature, object[] args)
{
    return (T)typeof(T).GetConstructor(signature).Invoke(args);
}

Teşekkürler dostum - Yöntemin bağlamı göz önüne alındığında bu çözümle gittim.
Hanshan

22
Tıpkı bir FYI gibi, bu alternatif olarak Aktivatör olarak da yazılabilir.CreateInstance (typeof (T), signature, args); daha fazla bilgi için msdn.microsoft.com/en-us/library/4b0ww1we.aspx adresine bakın .
Chris Baxter

@Calgary Coder: Bir tür [] imzası için ne kullanılır, imzayı açıkça belirtmeden CreateInstance'ı doğrudan parametrelerle çağırabilirsiniz. Her iki durumda da eşleşen bir kurucu yoksa MissingMethodException özel kodunu alırsınız.
Boris B.

4
Bu sizin için en uygun cevap olsa bile, açıkçası topluluk için en iyi yanıt bu değildir. Bu soruyu arayan insanlar gerçekten cevabı aşağıdan arıyorlar.
Tuzak

Peki bu bağlam tam olarak nedir? Lütfen orijinal soruya ekleyin.
James

18

Sadece tamamlamak için, buradaki en iyi çözüm genellikle bir fabrika işlev argümanı gerektirmektir:

T GetObject<T>(Func<T> factory)
{  return factory(); }

ve buna şöyle bir şey deyin:

string s = GetObject(() => "result");

Gerekirse mevcut parametreleri istemek veya kullanmak için bunu kullanabilirsiniz.


16

Yeni kısıt iyidir, ama T de bir değer türü olmak gerekirse, bunu kullanın:

protected T GetObject() {
    if (typeof(T).IsValueType || typeof(T) == typeof(string)) {
        return default(T);
    } else {
       return (T)Activator.CreateInstance(typeof(T));
    }
}

7

Bu C # 4 olarak etiketlendiğinden. Açık kaynak çerçeve ImpromptuIntereface ile , yapıcıyı çağırmak için dlr'ı kullanacaktır. Ancak ana avantajı, C # 4.0 isteğe bağlı parametreleri olan yapıcıları doğru bir şekilde işlemesi, Aktivatörün yapamayacağı bir şey.

protected T GetObject(params object[] args)
{
    return (T)Impromptu.InvokeConstructor(typeof(T), args);
}

4

Bunu elde etmek için aşağıdaki kodu denedim:

  protected T GetObject<T>()
    {
        T obj = default(T);
        obj =Activator.CreateInstance<T>();
        return obj ;
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.