[C#] Gebruik generics

Pagina: 1
Acties:

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Ik heb de volgende klasse:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class List
    {
        private LinkedList<Item> items;

        public List()
        {
            items = new LinkedList<Item>();
        }

        public LinkedList<Item> Items
        {
            get { return items; }
        }
}
Tevens is er een klasse Item.

Vervolgens wil ik het eerste item eruit halen:
code:
1
Item item = list.Items.First;

Maar helaas wil dit niet:
Cannot implicitly convert type 'System.Collections.Generic.LinkedListNode<Test.Item>' to 'Test.Item'
Hoe kan dit en hoe krijg ik wel een item uit mijn lijst?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
Mischien dat dit werkt:
Java:
1
Item item = (Item)list.Items.First;

Noushka's Magnificent Dream | Unity


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Michali schreef op donderdag 25 augustus 2005 @ 14:49:
Mischien dat dit werkt:
Java:
1
Item item = (Item)list.Items.First;
Helaas, dat werkt niet:
Cannot convert type 'System.Collections.Generic.LinkedListNode<Test.Item>' to 'Test.Item'

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:54
Mja, ik heb hier nu geen .NET 2.0 staan, maar is het niet zo dat jouw linked list elementen bevat van het type LinkedListNode, en dat die LinkedListNode dan een object bevat van het type dat jij hebt aangegeven ?

Zo dus:
code:
1
Item item = list.Items.First.Value;


De foutmelding zegt nl. dat hij geen LinkedListNode naar Item kan casten, wat logisch is.
Volgens mij zit Item in de LinkedListNode.

[ Voor 21% gewijzigd door whoami op 25-08-2005 14:56 ]

https://fgheysels.github.io/


Verwijderd

Eehm die First returnt bijkbaar iets van het type 'System.Collections.Generic.LinkedListNode<Test.Item>' en niet van het type Test.Item. Casten kan dus niet. Die Node heeft een waarde van het type Test.Item. Zo'n dingen zoek je best op in msdn: http://msdn2.microsoft.co...hf4c754(en-us,vs.80).aspx

spuit 11 enzo..

[ Voor 8% gewijzigd door Verwijderd op 25-08-2005 14:57 . Reden: spuit 11 enzo ]


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Value is het inderdaad, weer wat geleerd! Heel erg bedankt!

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Michali:
Mischien dat dit werkt:
Java:
1
Item item = (Item)list.Items.First;
Zou nogal sneu zijn. Hebben ze eindelijk generics bedacht, moet je nog casten.

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
drm schreef op donderdag 25 augustus 2005 @ 15:06:
[...]
Zou nogal sneu zijn. Hebben ze eindelijk generics bedacht, moet je nog casten.
Idd, even niet aan gedacht :)

Noushka's Magnificent Dream | Unity


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nu dit toch een C# generics topic is kan ik mijn vraag hier ook wel deponeren :P

In java heb je zoiets:
Java:
1
2
3
4
class Collection<T>
{
    void addAll(Collection<U extends T> c);
}

(onder voorbehoud van notatiefouten)

Wat je hier zegt is dat je aan een collection alle elementen van een andere collection toe kunt voegen, vermits elk element in de andere collection een subclass is van de ene. Oftewel, als je een lijst hebt met objecten dan kun je daar een lijst met strings in inserten, en dat is ook logisch want elke string is immers een object. In java noemen ze dit een super bound constraint als ik me niet vergis.

In .Net kun je wel constraints opgeven, maar volgens mij geen super bound constraints. Dit werkt iig niet:
C++:
1
2
3
4
5
6
generic<class T> class Collection
{
    generic<class U>
        where U : T
    void addAll(Collection<U> c);
};


Dit geeft bij mij de error dat je geen constraint kunt leggen op een generic type. Is dit nou echt een onoverkomelijkheid van .Net 2.0 of kan het op een andere manier?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Kaassoevlee schreef op donderdag 25 augustus 2005 @ 14:44:
Ik heb de volgende klasse:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class List
    {
        private LinkedList<Item> items;

        public List()
        {
            items = new LinkedList<Item>();
        }

        public LinkedList<Item> Items
        {
            get { return items; }
        }
}
Slecht idee. Als je een collectie als member hebt, dan wil je vrijwel nooit unrestricted
access aan je class users geven. Nou denk je misschien, ik heb alleen een getter.
Maar die getter geeft wel de hele lijst terug. Je kunt weliswaar geen compleet nieuwe
lijst setten, maar wel de bestaande lijst leeggooien en vullen met nieuwe inhoud. Dat
komt op hetzelfde neer.

(En dat komt weer omdat C# geen 'const' qualifier heeft)

[ Voor 4% gewijzigd door MSalters op 25-08-2005 15:35 . Reden: [/quote] ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • stylee
  • Registratie: December 2000
  • Laatst online: 04-09-2021

stylee

blah zeg ik je

.oisyn schreef op donderdag 25 augustus 2005 @ 15:27:
...
Dit geeft bij mij de error dat je geen constraint kunt leggen op een generic type. Is dit nou echt een onoverkomelijkheid van .Net 2.0 of kan het op een andere manier?
Met C# 2.0 generics kun je constraints als volgt gebruiken:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class LinkedList<K,T> where K : IComparable
{
   T Find(K key)
   {
      Node<K,T> current = m_Head;
      while(current.NextNode != null)
      {
         if(current.Key.CompareTo(key) == 0)
            
            break;
         else      
            
            current = current.NextNode;
      }
      return current.Item; 
   }
   //Rest of the implementation 
}


Zie voor meer informatie "Generic Constraints" op msdn (http://msdn.microsoft.com.../html/csharp_generics.asp)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je leest niet wat ik zeg. Stel je hebt een generic class met type T. En daarin een generic functie met type U, en je wilt een constraint leggen dat U altijd een subclass is van T. Kan dat of kan dat niet?

M'n Visual C++ 2005 express beta 2 zegt iig van niet, niet op de manier die ik liet zien iig :).

[ Voor 99% gewijzigd door .oisyn op 25-08-2005 16:58 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • EfBe
  • Registratie: Januari 2000
  • Niet online
.oisyn schreef op donderdag 25 augustus 2005 @ 16:18:
Je leest niet wat ik zeg. Stel je hebt een generic class met type T. En daarin een generic functie met type U, en je wilt een constraint leggen dat U altijd een subclass is van T. Kan dat of kan dat niet?
Je kunt alleen interfaces specificeren in de where clause, geen class types. Ja ik heb het ook niet bedacht. Ik weet niet welke gek die constraints verzonnen heeft, maar er zitten ernstige tekortkomingen in:
1) een class is ook een interface, maar dat kan hij niet aan
2) je kunt geen operators specificeren, en operator overloads zijn static gedefinieerd, dus niet in een interface gedefinieerd, dus kun je geen generic methods maken die een operator gebruiken op een generic type (hoezee, wat een vooruitgang!)

Dus die generics zijn eigenlijk alleen handig voor het typed maken van collections.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

EfBe schreef op donderdag 25 augustus 2005 @ 17:22:
[...]

Je kunt alleen interfaces specificeren in de where clause, geen class types.
Meen je dat? Dit compilet en runt prima bij mij:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
ref class Base { };
ref class Derived : public Base { };

generic<class T>
    where T : Base
ref class Test
{
};

int main() 
{
    Test<Derived^> ^ t = gcnew Test<Derived^> ();
}


C++/CLI dan weliswaar, maar dat moet niet uitmaken lijkt me?
2) je kunt geen operators specificeren, en operator overloads zijn static gedefinieerd, dus niet in een interface gedefinieerd, dus kun je geen generic methods maken die een operator gebruiken op een generic type (hoezee, wat een vooruitgang!)
Dit compilet (wederom) wel:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

using namespace System;

generic<class T, class U> value class Pair
{
public:
    T value1;
    U value2;

    Pair(T t, U u) : value1(t), value2(u) { }
    void Write() { Console::WriteLine("Pair({0}, {1})", value1, value2); }
};

generic<class T>
value class Test
{
public:
    T value;

    Test(T t) : value(t) { }

    generic<class U>
    static Pair<T,U> operator +(Test<T> t1, Test<U> t2)
    {
        return Pair<T,U>(t1.value, t2.value);
    }
};

int main() 
{
    Test<int> t1 (4);
    Test<float> t2 (23.4f);
    (t1 + t2).Write();
}


Punt is alleen dat het niet runt wegens een System.BadImageFormatException :P. Zitten nog wat bugs in de C++/cli compiler, een ToString() aanroepen op een value-type in een generic class geeft dezelfde exception bij het runnen. Ik kreeg het ook niet voor elkaar om een ToString te implementeren in Pair overigens, vandaar de wat rare manier.
Dus die generics zijn eigenlijk alleen handig voor het typed maken van collections.
Als wat jij zegt idd klopt dan is het idd een baggerimplementatie zeg :/

[ Voor 5% gewijzigd door .oisyn op 25-08-2005 18:36 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:54
.oisyn schreef op donderdag 25 augustus 2005 @ 15:27:

Wat je hier zegt is dat je aan een collection alle elementen van een andere collection toe kunt voegen, vermits elk element in de andere collection een subclass is van de ene. Oftewel, als je een lijst hebt met objecten dan kun je daar een lijst met strings in inserten, en dat is ook logisch want elke string is immers een object. In java noemen ze dit een super bound constraint als ik me niet vergis.

Dit geeft bij mij de error dat je geen constraint kunt leggen op een generic type. Is dit nou echt een onoverkomelijkheid van .Net 2.0 of kan het op een andere manier?
Dit lukt bij mij nochtans:
(as in: het compilet)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Class2<T>
{
        private class Class3<U> where U : T
        {
            U test;

            public Class3( U i )
            {
                test = i;
            }

        }        
}

https://fgheysels.github.io/


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
whoami schreef op donderdag 25 augustus 2005 @ 20:17:
[...]


Dit lukt bij mij nochtans:
(as in: het compilet)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Class2<T>
{
        private class Class3<U> where U : T
        {
            U test;

            public Class3( U i )
            {
                test = i;
            }

        }        
}
maar compileert dit dan ook. Want dat is volgens mij wat oisyn bedoelt ( Mischien is de syntax niet helemaal goed want heb nog nooit iets met generics gedaan )

C#:
1
2
3
4
5
6
public class Collection<T>
{
    public void AddCollection( Collection<U> collection ) where U : T
    {
    }
}

Dus niet dat je een constraint bij de definitie van de class vastlegt maar dat je een constraint geeft aan de parameter die meegegeven moet worden aan een method.

Ik heb hier nu even geen vs.net 2005 geinstalleerd dus kan het niet uitproberen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • EfBe
  • Registratie: Januari 2000
  • Niet online
.oisyn schreef op donderdag 25 augustus 2005 @ 17:45:
[...]


Meen je dat? Dit compilet en runt prima bij mij:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
ref class Base { };
ref class Derived : public Base { };
generic<class T>
    where T : Base
ref class Test
{
};

int main() 
{
    Test<Derived^> ^ t = gcnew Test<Derived^> ();
}


C++/CLI dan weliswaar, maar dat moet niet uitmaken lijkt me?

Punt is alleen dat het niet runt wegens een System.BadImageFormatException :P. Zitten nog wat bugs in de C++/cli compiler, een ToString() aanroepen op een value-type in een generic class geeft dezelfde exception bij het runnen. Ik kreeg het ook niet voor elkaar om een ToString te implementeren in Pair overigens, vandaar de wat rare manier.
Jaaaa, C++! maar dat is geen C# :). C#'s implementatie is veel stricter. Ik ga het zo ff uitproberen, of ik ook een class als restrictie kan gebruiken, maar de where syntax leest alsof dat niet gaat.

[ Voor 28% gewijzigd door EfBe op 26-08-2005 10:01 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Ok, ik had het dus mis! (gelukkig :))
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System;
using System.Collections.Generic;
using System.Text;

namespace TestGenerics
{
    public interface IFoo
    {
        void Foo();
    }

    public class Class1//: IFoo
    {
        public virtual void Foo()
        {
            Console.WriteLine("Class1:Foo");
        }
    }


    public class Class2 : Class1
    {
        public override void Foo()
        {
            Console.WriteLine("Class2:Foo");
        }
    }

    public class Class3 : Class1
    {
        public override void Foo()
        {
            Console.WriteLine("Class3:Foo");
        }
    }

    public class Class4<T> where T : Class1// IFoo
    {
        public void Test(T t)
        {
            t.Foo();
        }
    }

    public class Class5
    {
        public Class5()
        {
            Class4<Class3> c = new Class4<Class3>();
            c.Test(new Class3());
        }
    }
}


compileert gewoon.
Weer wat geleerd (vond het al raar, maar ik interpreteerde die where syntaxis dus verkeerd).

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

whoami schreef op donderdag 25 augustus 2005 @ 20:17:
[...]


Dit lukt bij mij nochtans:
(as in: het compilet)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Class2<T>
{
        private class Class3<U> where U : T
        {
            U test;

            public Class3( U i )
            {
                test = i;
            }

        }        
}
In C++/CLI geeft dat
error C3218: 'T' : type not allowed as a constraint
Maar goed, ik gooi het maar op een buggy compiler dan :) (Als je in de MSDN naar die error zoekt dan geven ze ook een voorbeeld waar ze een native class gebruiken als een constraint. Nee dat mag niet nee, logisch, maar daardoor krijg ik wel het idee dat ze hier de verkeerde error geven)

Waar kun je beta bugs eigenlijk melden?

[ Voor 22% gewijzigd door .oisyn op 26-08-2005 12:00 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
.oisyn: In java noemen ze dit een super bound constraint als ik me niet vergis.
Het wordt een upper bound genoemd, of simpelweg bound in het geval van type variabelen, omdat type variabelen alleen maar upper bounds kunnen hebben.

Voor Java is de term upper bound is een stuk duidelijker dan super bound omdat wildcards in Java ook een lower bound kunnen hebben. De syntax voor lower bounds gebruikt het woord super, dus je voelt de verwarring al aankomen :o .

code:
1
  List<? super SubType>


Lower bounds kwamen ook aan de orde in dit topic: [rml][ Java] Generics vraag[/rml]

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 21:33

.oisyn

Moderator Devschuur®

Demotivational Speaker

Euh right, het kwam idd uit die topic maar had het verkeerd onthoden :P. Maar goed, lower bound ondersteunt .Net al helemaal niet, ik mag hopen dat het nog komt in de final release maar heb er een hard hoofd in :/

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • EfBe
  • Registratie: Januari 2000
  • Niet online
mbravenboer schreef op vrijdag 26 augustus 2005 @ 12:10:
[...]

Het wordt een upper bound genoemd, of simpelweg bound in het geval van type variabelen, omdat type variabelen alleen maar upper bounds kunnen hebben.

Voor Java is de term upper bound is een stuk duidelijker dan super bound omdat wildcards in Java ook een lower bound kunnen hebben. De syntax voor lower bounds gebruikt het woord super, dus je voelt de verwarring al aankomen :o .

code:
1
  List<? super SubType>
DAT zocht ik inderdaad, dit wordt niet door .NET ondersteund in 2.0, wellicht in 3.0 (maar ja, dat is nog niet eens uitgedesigned, dus alles kan)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com

Pagina: 1