[ dejan85 @ 08.01.2008. 14:51 ] @
Ucim genericke klase u c#, prvo sto pokusavam to je da saberem dva broja proizvoljnog tipa.
Code:

    public class Klasa<T>
    {
        public T saberi(T a, T b) { return a + b; }
    }
   static void Main(string[] args)
        {
           Klasa<int> b = new Klasa<int>();            
           Console.WriteLine(b.saberi(1,2));
        }
Ovo ne radi jer ne moze da primeni operator + na tip T. Ne znam kao prvo kako ovo treba da se prepravi da radi, a drugo nije mi jasno zasto ne moze da ga kompilira, zar ne treba to sve da prodje kompiliranje, pa ako su tipovi neodgovarajuci da onda program pukne. Koliko znam tako je u c++. Meni ovo deluje kao osnovni primer za genericke klase, ne znam zasto u svim knjigama stavljaju primer samo za stek, stablo, listu...
[ Fedya @ 08.01.2008. 14:57 ] @
To naravno ne moze tako. C# je type safe, i ta bezbednost se obavlja na nivou komplajliranja.
T u tvom slucaju znaci bilo koji tip, a taj tip mozda (cak vrlo vervatno) nema operator+ (posto klasa Object nema operator+) komplajler to zna i zato ti ne dozvoljava kompajliranje.
[ dejan85 @ 08.01.2008. 15:05 ] @
Pa... jel ne moze tako ili ne moze nikako. Cemu mi onda sluze ovakve klase kad mogu da napravim dve matrice sa elementima tipa T a ne mogu da ih saberem.
[ Fedya @ 08.01.2008. 15:13 ] @
Ne moze nikako dok god koristis operator+.
Kada bi se ovo kompajliralo (a nece), moglo bi da radi dok god koristis klase int, long i sl. ili one koje imaju rucno napisan operator+. Za sve druge (lupam DataReader, Person... bilo sta) ovakav kod nema nikakvog smisla.

Verovatno zato osnovni primeri za generics koriste liste i sl. posto im je to i primarna uloga.

Ako hoces matrice, napravi klasu matrice pregazi operator+ i koristi to, generics nisu za to...
[ mmix @ 08.01.2008. 15:21 ] @
Iz msdn-a:

Citat:

The following are the key differences between C# Generics and C++ templates:

C# generics do not provide the same amount of flexibility as C++ templates. For example, it is not possible to call arithmetic operators in a C# generic class, although it is possible to call user defined operators.


Al nije da ne moze
alternativno mozes da radis drugu stvar, da koristis reflection da vidis da li T ima operator+ i ako ima da ga primeni ako ne baci exception

[ Shadowed @ 08.01.2008. 16:08 ] @
Citat:
dejan85: Ucim genericke klase u c#, prvo sto pokusavam to je da saberem dva broja proizvoljnog tipa.

Stvar je u tome da to T uopste ne mora da bude broj proizvoljnog tipa, vec moze da bude bilo sta, neko moze da uradi sledece:
Code:

static void Main(string[] args)
        {
           Klasa<Bitmap> b = new Klasa<Bitmap>();            
           Console.WriteLine(b.saberi(new Bitmap(100, 200), new Bitmap(200, 300));
        }


Sta bi se desilo u ovom slucaju? Tesko da bi se Bitmap klase mogle sabrati :)
Postoje generic type constraints ali nije mi poznato da se moze proveriti da li T ima operator + tako da ako bas hoces da koristis generics za ovo onda jedino da preko reflection-a proveris ima li taj operator ali ti onda nece prijaviti gresku prilikom kompjaliranja vec tek u toku izvrsavanja (doduse, tu mozes preduzeti odgovarajuce korake za slucaj greske).

Edit: Eto sta se desi kad pocnes da pises odgovor pa pauziras ceo sat. :)
[ dejan85 @ 08.01.2008. 16:36 ] @
Ok, skapirao sam, moracu da promenim razmisljanje jer nece sve lepo kao u c++-u :(
[ Shadowed @ 08.01.2008. 16:39 ] @
http://msdn2.microsoft.com/en-us/library/aa479859.aspx

Citat:

You cannot constrain a generic type parameter to support any specific operator. There is therefore no way to compile the following code:
Code:

public class Calculator<T>
{
   public T Add(T argument1,T argument2)
   {
      return argument1 + argument2; //Does not compile 
   }
   //Rest of the methods 
}



Dakle kao sto mmix rece (a i zar moze drugacije ), jedino rpeko reflection-a
[ mmix @ 08.01.2008. 19:29 ] @
Zapravo, malo sam se zabavio mentalnom gimnastikom i dosao do zakljucka da ne moze ni refleksijom, operatori nad value tipovima ne postoje u metadata i kompajler opet mufte na kvarno sabira varajuci. Zato ni ne moze da se primeni na generics-e. Jedini nacin je quick'n'dirty kroz code dom:

Code:

    public class Klasa<T> where T:struct 
    {
        private static MethodInfo adder = BuildAdder();
        private static MethodInfo BuildAdder()
        {
            Type tT = typeof(T);
            string code = string.Format("using System; public class C {{ " + 
                        "public static {0} Add({0} a, {0} b){{return a+b;}}}}", tT.ToString());

            CSharpCodeProvider cs = new CSharpCodeProvider();
            CompilerParameters cp = new CompilerParameters(new string[] {"System.dll"});
            cp.GenerateInMemory = true;

            CompilerResults cr = cs.CompileAssemblyFromSource(cp, new string[] { code });
            return cr.CompiledAssembly.GetType("C").GetMethod("Add");
        }

        public T saberi(T a, T b) 
        {
            T c = (T)adder.Invoke(null, new object[]{a, b});
            return c;
        }
    }
[ Shadowed @ 08.01.2008. 20:12 ] @
S' tim da valja napomenuti da ovo i dalje nece raditi sa bilo kojim tipovima (kao sto generics dozvoljava) tj. strukturama sto je ovde ograniceno vec samo onim koje podrzavaju sabiranje. Jedino sto moze da se iskompajlira jer prevodi generic u konkretni tip.
[ dejan85 @ 08.01.2008. 20:50 ] @
Vidim ja da sam daleko od toga da nesto ovako sam napisem...