2012-03-12 35 views
9

Genel bir yazdırma işlevine sahip olmak istiyorum ... PrintGeneric (T) ... aşağıdaki durumda ne eksik? @Ash Burlaczenko sen reallllly bu isterseniz, bir anahtar kelimeden sonra bir değişken adı olamaz dediği gibiC#: Bir Genel Nesneyi Geçirme

Her zaman olduğu gibi sizin yardım/fikir takdir

...

public interface ITest 
{} 

public class MyClass1 : ITest 
{ 
    public string myvar = "hello 1"; 
} 

public class MyClass2 : ITest 
{ 
    public string myvar = "hello 2"; 
} 

class DoSomethingClass 
{ 

    static void Main() 
    { 
     MyClass1 test1 = new MyClass1(); 
     MyClass2 test2 = new MyClass2(); 

     Console.WriteLine(test1.myvar); 
     Console.WriteLine(test2.myvar);    
     Console.WriteLine(test1.GetType()); 

     PrintGeneric(test1); 
     PrintGeneric<test2.GetType()>(test2); 
    } 

    // following doesn't compile 
    public void PrintGeneric<T>(T test) 
    { 
     Console.WriteLine("Generic : " + test.myvar); 
    } 
} 
+1

'var' değişken adı olamaz. Gerçek kodunuzu gösterebilir misiniz. –

+3

@AshBurlaczenko Doğru değil. "var", C# 3.0'da eklenen bir bağlamsal anahtar kelimedir. Bunu bir tanımlayıcı adı olarak kullanabilirsiniz. Benzer şekilde, çoğu bağlamdaki tanımlayıcı adları olarak "getiri", "select", "from" vb. Kullanabilirsiniz. –

+0

aslında "var" sadece Console.WriteLine kullanmadan işe yaramadı ... ama bu bir anahtar kelimeyi tanımlayıcı adı olarak kullanmak benim için kötüydü ... – user1229895

cevap

19

T, bir şey olabileceği için derlenmiyor ve her şey myvar alanına sahip olmayacak.

public ITest 
{ 
    string myvar{get;} 
} 

ve özellik olarak sınıflara üzerinde uygulanması:

Sen ITest üzerinde myvar bir özellik yapabilir

public class MyClass1 : ITest 
{ 
    public string myvar{ get { return "hello 1"; } } 
} 

ve sonra yöntem üzerinde genel bir sınırlama koymak:

public void PrintGeneric<T>(T test) where T : ITest 
{ 
    Console.WriteLine("Generic : " + test.myvar); 
} 

ama bu durumda dürüst olmak gerekirse, daha iyi st bir ITest geçen:

public void PrintGeneric(ITest test) 
{ 
    Console.WriteLine("Generic : " + test.myvar); 
} 
+0

ITest'e bir özellik ekledim, ancak o zaman bana mantıklı geliyor MyClass1/MyClass2 ... uygulamak gerektiğini söyler, ama sonra zaten myvar – user1229895

+0

Oh evet için bir tanımlama içeren bir hata alıyorum, daha sonra özellikleri sınıfları uygulamak. Cevabımı size göstermek için güncellendi. – jonnystoten

+0

Jenerik için PrintGeneric (test2) öğesini deneyin ve PrintGeneric (ITest testi) için bir 'Yalnızca atama, çağrı, arttırma, azalma ifadesi olarak kullanılan' ve PrintGeneric (test1) 'i deneyin. .and "Statik olmayan alan için bir nesne referansı gerekiyor" – user1229895

0

public void PrintGeneric<T>(T test) where T: ITest 
{ 
    Console.WriteLine("Generic : " + [email protected]); 
} 

deneyin anahtar kelimesinden çıkmak için sembol ile önek

+1

Bu işe yaramayacak, 'ITest'' var' adlı bir üye yok. –

+0

Sadece ITest, özellik varını belirtirse işe yarayacak. Örnekte olduğundan emin değilim. –

+0

evet, ITT'ye eklenmesi gereken –

2

Genel yöntemde T bir tür için yalnızca bir yer tutucudur. Ancak, derleyici, çalışma zamanı kullanılan beton türü (ler) hakkında hiçbir şey bilmiyor, bu yüzden bir var üye olacaklarını varsayalım.

bu aşmak için her zamanki gibi türleri belirli bir arayüz uygulamak kullanılan emin olmak için yöntem ilanına bir genel tür kısıtlamasını eklemektir (senin durumunda, bu ITest olabilir):

public void PrintGeneric<T>(T test) where T : ITest 

Sonra Bu arayüzün üyeleri, yöntem içinde doğrudan kullanılabilir. Ancak, ITest şu anda boş, yöntem içinde kullanımını etkinleştirmek için orada ortak şeyler bildirmeniz gerekir.

2

Sen jenerik tip T hakkında daha fazla bilgi sağlamak gerekecek. Geçerli PrintGeneric yönteminde, T, var üye olmayan bir string olabilir.

Bir alanda

public interface ITest 
{ 
    string var { get; } 
} 

yerine bir mülke var değiştirmek Ve PrintGeneric yöntemine bir kısıtlamayı where T: ITest eklemek isteyebilir.

6

Sen şeylerin en azından bir kaç eksik: Kullanmak edememesi için yansıma kullandığınız sürece

  • , tip argümanlar, derleme zamanında bilinmesi gerekir

    PrintGeneric<test2.GetType()> 
    
    ... bu durumda gerek yoktur rağmen etmek zaten

  • PrintGeneric anda T hakkında bir şey biliyor, bu yüzden derleyici c gelmez

    • T sınırlamak için PrintGenericITest arayüzde bir özelliği koyun ve değiştirin::

      public void PrintGeneric<T>(T test) where T : ITest 
      { 
          Console.WriteLine("Generic : " + test.PropertyFromInterface); 
      } 
      
    • bir özellik koy üyesi T

    Seçenek denilen bulmak an't ITest arayüzünde ve jenerikleri tamamen kaldırın:

    yerine jenerik
    public void PrintGeneric(ITest test) 
    { 
        Console.WriteLine("Property : " + test.PropertyFromInterface); 
    } 
    
  • kullanın dinamik yazarak C# kullanıyorsanız 4

+1

yazım hatası olarak kullanılabilir Jon? Jenerikleri kaldır dediniz, ancak yöntemde hala var mı? –

+2

@SteveHaigh: Doh, telefonla yazıp konuştuğum aynı zamanda. Sabit, teşekkürler. –

+0

ilk seçeneği deniyor ... "String myvar {get;}" i ITest'e ekliyorum ... fakat MyClass1/MyClass2'nin 'ITest.myvar' arayüzünü uygulamadığını belirten bir hata mesajı alıyorum ... ekleme "string myvar MyClass1/MyClass2 için {get;} ", zaten tanımlanmış olduğunu söyleyen derleme hatasıyla sonuçlanıyor? – user1229895

1

:

public interface ITest 
{ 
    string Name { get; } 
} 

ITest ürününü c lasses:

public class MyClass1 : ITest 
{ 
    public string Name { get { return "Test1"; } } 
} 

public class MyClass2 : ITest 
{ 
    public string Name { get { return "Test2"; } } 
} 

Sonra ITest için, sizin jenerik Print fonksiyonunu kısıtlamak: Bu bir anahtar kelime olarak

public void Print<T>(T test) where T : ITest 
{ 
} 
+0

Cevabın Ash'ın bu soru hakkındaki yorumuna bakın. 'Var', 'getiri' vb. Gibi tanımlayıcı adı olarak kullanabilirsiniz, ancak bu muhtemelen harika bir fikir değildir. İçeriğe dayalı bir anahtar kelime. Kendiniz için doğrulamak için 'int var; 'ı deneyin. –

+0

@MehrdadAfshari, ah .. Bunun farkında değildim. Eh, bugün öğrendim. Ama evet, aslında yapacağım bir şey değil :) –

İlgili konular