Avatar billede CodingJoe Nybegynder
06. januar 2011 - 23:27 Der er 44 kommentarer og
1 løsning

Hente størrelse på en generic T der er et array

Jeg har defineret en generisk metode, der tager et (T t) som parameter. Det går helt fint...og her er ingen problemer...ved debug kan jeg se at t indeholder mit ArrayList med data. Hvordan finder jeg størrelsen på mit array. Jeg har forsøgt med reflection:
t.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); og jeg kan se at Count ligger på index[1], men det er jo teksten.

HVordan er det lige man finder størrelsen på mit array?
Avatar billede arne_v Ekspert
06. januar 2011 - 23:32 #1
Der er en GetValue metode til at hente værdien af en property med.
Avatar billede arne_v Ekspert
06. januar 2011 - 23:33 #2
Men hvis du ved at det er en ArrayList så skal du nok erklære argumentet som ArrayList og så kan du bruge Count property direkte. Eller langt bedre lad det være List<T> !
Avatar billede CodingJoe Nybegynder
06. januar 2011 - 23:34 #3
Hmmm dvs. jeg altså skal bruge:

var properties = t.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

Jeg tror, jeg næsten har den...men kan ikke se nogen GetValue i min intellisense :(
Avatar billede CodingJoe Nybegynder
06. januar 2011 - 23:35 #4
Måske denne ->
var count = (int) properties.GetValue(1);
Avatar billede CodingJoe Nybegynder
06. januar 2011 - 23:36 #5
T er faktisk en List<T>. Så jeg kan i virkeligheden bare lade min signatur hedde (List<T> t) istedet for (T t)?
Avatar billede CodingJoe Nybegynder
06. januar 2011 - 23:38 #6
var count = (int) properties.GetValue(1); 
Gav en invalid cast exception.

Min værdi der kommer ind er en List<Foo> som jeg ville have T til at repræsentere i min generiske metode.
Avatar billede CodingJoe Nybegynder
06. januar 2011 - 23:40 #7
Det viser sig, jeg får "Int32 Count" tilbage fra min GetValue(1);
Avatar billede CodingJoe Nybegynder
06. januar 2011 - 23:49 #8
Sidder stadigvæk fast her :(
Avatar billede Syska Mester
07. januar 2011 - 00:08 #9
Hvad er det reelt set du prøvet på? Siden du vil finde størrelse på dit T t ? som du siger er en ArrayList ... hvis du allerede ved det er en ArrayList så er det vel lidt mærkeligt at finde størrelse på det ...

Hvad nu hvis en anden bruger det som en T t der er en integer? eller en SqlConnection ?

mvh
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 00:21 #10
Okay Buzzz...alting virker meget mærkeligt for dig...hvad jeg synes er mærkeligt er at du slet ikke har leget med generics...jeg kan ikke vide, hvilken type List<foo1> List<foo2>, jeg får ind. De kommer ind som en parameter på min generiske metode.
Jeg skal håndtere dette i min kode...jeg har lavet noget lignende før med succes, men bare ikke med arrays... Finder jeg størrelsen...er jeg ret langt fremme i min kode...

Synes du skal sætte dig ind i generics....Jeg har lavet en constraint på min metode, så den kun kan kaldes med arrays...ellers kommer der en fejl. Desuden hedder metoden også noget med array, så man er selv udenom at smide noget crap ind.
Avatar billede Syska Mester
07. januar 2011 - 00:30 #11
Nej, det virker ikke mærkeligt for mig, men vil bare gerne vide hvad du prøver på, der det virker mytisk i min verden via reflection at skulle kigge efter antal Element i dit Array.

Har jeg skrevet jeg ikke bruger Generics ? :-)

Derfor jeg efterlyser lidt hvad du prøver på.

Hvis du alligevel har en constraint på at det skal være et Array ... eller what ever ... hvad er der så Generic ved det ?

Hvorfor så ikke bruge IList<T> eller List<T> som Arve_v også skriver i starten ?
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 00:37 #12
Fordi det er ikke er det, der kommer ind.

List<Foo> foo = new List<Foo>();

Kald til min generiske metode...

SomeHelperClass.DoStuffWithMyArray(foo);

Simplificeret signatur på min generic metode:
public static void DoStuffWithMyArray<T>(T t) {

Jeg kan jo ikke skrive List<T> i min signatur, da det vil være en List<> af en List<foo>.
Avatar billede Syska Mester
07. januar 2011 - 00:39 #13
DoStuffWithMany<T>(IList<T> list)

Burde virke ...

Men hvis du vil den anden vej:
ArrayList t = new ArrayList();
var propertyInfos = t.GetType().GetProperties();
var propertyInfo = propertyInfos.Single(a => a.Name == "Count");
var value = propertyInfo.GetValue(t, null);
Console.WriteLine(value);

mvh
Avatar billede Syska Mester
07. januar 2011 - 00:41 #14
private static void DoStuffWithMany<T>(IList<T> list)
        {
            Console.WriteLine(list.Count);
        }


Det kan du så kalde med:
private static void Main(string[] args)
        {
            IList<int> list2 = new List<int>();
            DoStuffWithMany(list2);
        }
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 00:46 #15
Der er altså et mismatch mellem din parameter og din signatur. Du har tydeligvis ikke testet det...
Avatar billede Syska Mester
07. januar 2011 - 00:48 #16
Nej ... det virker ... det er bare en liste med en liste ... 100% valid.

Du kan også:
private static void DoStuffWithMany<T>(T list) where T : ArrayList
{
    Console.WriteLine(list.Count);
}
Avatar billede Syska Mester
07. januar 2011 - 00:53 #17
Og nej, det er faktisk ingengnag en liste med en list ...

Via inference eller hvad det nu hedder finder den selv ud af typen.
using System;
using System.Collections.Generic;

namespace Executor
{
    public class Program2
    {
        private static readonly Random _Random = new Random();

        private static void DoStuffWithMany<T>(IList<T> list)
        {
            Console.WriteLine(list.Count);
            foreach (T t in list)
            {
                Console.WriteLine(t);
            }
        }

        private static void Main(string[] args)
        {
            IList<int> list2 = new List<int>();
            list2.Add(20);
            DoStuffWithMany(list2);
        }
    }
}
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:00 #18
Virker ikke desværre...

Jeg prøver igen imorgen. Tak for tiden.
Avatar billede Syska Mester
07. januar 2011 - 01:08 #19
Alt hvad jeg har postet virker og er testet ... så hvad er det som ikke virker ?

Prøv at komme med hele din metode og hvordan du kalder den.

mvh
Avatar billede arne_v Ekspert
07. januar 2011 - 01:21 #20
Eksempel med GetProperty GetValue og List<T>:

using System;
using System.Collections.Generic;

namespace E
{
    public class Program
    {
        public static string VeryBad<T>(T o)
        {
            int len = (int)typeof(T).GetProperty("Count").GetValue(o, null);
            return (string)typeof(T).GetProperty("Item").GetValue(o, new object[] { (len-1)/2});
        }
        public static T Better<T>(List<T> o)
        {
            int len = o.Count;
            return o[(len-1)/2];
        }
        public static void Main(string[] args)
        {
            List<string> lst = new List<string>();
            lst.Add("A");
            lst.Add("BB");
            lst.Add("CCC");
            Console.WriteLine(VeryBad(lst));
            Console.WriteLine(Better(lst));
            Console.ReadKey();
        }
    }
}
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:37 #21
Arne...du er min helt...denne linje:

int len = (int)typeof(T).GetProperty("Count").GetValue(o, null);

Var lige præcis det, jeg havde brug for at vide...jeg var der næsten men røg af ved GetValue's anden parameter, som du blot har sat til null...jeg faldt ned ved object[] index...og var ikke sikker, hvad jeg skulle smide med ind her...

Fuld points til dig...tusinde tak. Du forstod mit problem i koden.

Smid gerne et svar ind
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:41 #22
Hvorfor er den verybad?
Avatar billede arne_v Ekspert
07. januar 2011 - 01:45 #23
Det er en generic metode hvor argumentet er af type T, men den giver fejl ved stort set alt andet en List<string>.

Pointen med generic er at undgå fejl ikke at skabe dem.

Better metode sikrer at den kun kaldes med en List<> og metoden kan returne enhver type ikke kun string.

Meget bedre!!
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:46 #24
Sjovt nok. Jeg får fejl...kan det have noget at gøre med at jeg ikke bruger string eller int...jeg bruger mit eget objekt i en List<Foo>. Jeg får en mismatch mellem typerne.
Avatar billede arne_v Ekspert
07. januar 2011 - 01:47 #25
Derudover skal du være opmærksom på at reflection metoder er forholdsvis dyre.

Kalder du Assembly.Load en gang er det ligegyldigt.

Men kalder du Type.GetProperty inden i en løkke som kaldes en million gange, så vil du opdage at performance lider.
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:47 #26
Kan man ikke lave en constraint på metoden?
where T : new(), List<T> agtigt uden af have testet den...
Avatar billede arne_v Ekspert
07. januar 2011 - 01:48 #27
VeryBad virker ikke med List<Foo>.

Du kan naturligvis rette metode til at returnere Foo og så virker den med Foo. Men ikke med Bar.

Better bør virke med List<string>, List<Foo> og List<Bar>.
Avatar billede arne_v Ekspert
07. januar 2011 - 01:49 #28
Du kan godt lave en constraint. Lad mig lige fixe et eksampel.
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:50 #29
Sjovt...jeg kan kun få verybad til at virke...jeg må kigge på det...men jeg fik et gennembrug...resten må jeg eftertjekke imorgen...ret sent her i DK og skal på arbejde imorgen.

Send du bare et svar ind.
Buzz du kan godt være med, så kan jeg hælde noget over hos dig
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:51 #30
Ahh mange tak...jeg ville nemlig satse på et constraint...som jeg faktisk også tidligere havde nævnt for buzzz
Avatar billede arne_v Ekspert
07. januar 2011 - 01:52 #31
using System;
using System.Collections.Generic;

namespace E
{
    public class Program
    {
        public static string VeryBad<T>(T o)
        {
            int len = (int)typeof(T).GetProperty("Count").GetValue(o, null);
            return (string)typeof(T).GetProperty("Item").GetValue(o, new object[] { (len-1)/2});
        }
        public static T2 PrettyBad<T,T2>(T o) where T : List<T2>
        {
            int len = (int)typeof(T).GetProperty("Count").GetValue(o, null);
            return (T2)typeof(T).GetProperty("Item").GetValue(o, new object[] { (len-1)/2});
        }
        public static T2 AlmostThere<T,T2>(T o) where T : List<T2>
        {
            int len = o.Count;
            return o[(len-1)/2];
        }
        public static T Better<T>(List<T> o)
        {
            int len = o.Count;
            return o[(len-1)/2];
        }
        public static void Main(string[] args)
        {
            List<string> lst = new List<string>();
            lst.Add("A");
            lst.Add("BB");
            lst.Add("CCC");
            Console.WriteLine(VeryBad(lst));
            Console.WriteLine(PrettyBad<List<string>,string>(lst));
            Console.WriteLine(AlmostThere<List<string>,string>(lst));
            Console.WriteLine(Better(lst));
            Console.ReadKey();
        }
    }
}
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:53 #32
Lol så faktisk er der ikke brug for constraints...
Better er always better... :D
Avatar billede arne_v Ekspert
07. januar 2011 - 01:55 #33
Med både string og int:

using System;
using System.Collections.Generic;

namespace E
{
    public class Program
    {
        public static string VeryBad<T>(T o)
        {
            int len = (int)typeof(T).GetProperty("Count").GetValue(o, null);
            return (string)typeof(T).GetProperty("Item").GetValue(o, new object[] { (len-1)/2});
        }
        public static T2 PrettyBad<T,T2>(T o) where T : List<T2>
        {
            int len = (int)typeof(T).GetProperty("Count").GetValue(o, null);
            return (T2)typeof(T).GetProperty("Item").GetValue(o, new object[] { (len-1)/2});
        }
        public static T2 AlmostThere<T,T2>(T o) where T : List<T2>
        {
            int len = o.Count;
            return o[(len-1)/2];
        }
        public static T Better<T>(List<T> o)
        {
            int len = o.Count;
            return o[(len-1)/2];
        }
        public static void Main(string[] args)
        {
            List<string> lst = new List<string>();
            lst.Add("A");
            lst.Add("BB");
            lst.Add("CCC");
            Console.WriteLine(VeryBad(lst));
            Console.WriteLine(PrettyBad<List<string>,string>(lst));
            Console.WriteLine(AlmostThere<List<string>,string>(lst));
            Console.WriteLine(Better(lst));
            List<int> lst2 = new List<int>();
            lst2.Add(1);
            lst2.Add(22);
            lst2.Add(333);
            // vil smide en fejl // Console.WriteLine(VeryBad(lst2));
            Console.WriteLine(PrettyBad<List<int>,int>(lst2));
            Console.WriteLine(AlmostThere<List<int>,int>(lst2));
            Console.WriteLine(Better(lst2));
            Console.ReadKey();
        }
    }
}
Avatar billede arne_v Ekspert
07. januar 2011 - 01:55 #34
Ja - Better er altid bedre!

:-)
Avatar billede arne_v Ekspert
07. januar 2011 - 01:57 #35
Bemærk at alle mine eksempler returnere det midterste element. Hvis din metode gør noget andet, så er der måske andre problemer som kommer ind.

Hvis du poster noget komplet kode der kan oversættes er det meget nemmere for os at finde og forklare fejl.
Avatar billede arne_v Ekspert
07. januar 2011 - 01:57 #36
Og et svar fra mig.
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 01:58 #37
Smid bare et svar ind... jeg kigger på det imorgen. kl. er 02 og jeg har vel leget nok med generics...(det er ikke engang arbejde, bare fun med generics) skal på arbejde imorgen...må hellere få mig de 5 timer jeg har tilbage inden jeg skal op igen :S

Mange tak og godnat fra DK
Avatar billede arne_v Ekspert
07. januar 2011 - 02:11 #38
Nu fik buzzzz så ikke noget.
Avatar billede Syska Mester
07. januar 2011 - 09:18 #39
Så endte du alligevel faktisk ud med det jeg skrev, omend Arne_v altid har en lidt anden og bedre måde at skrive tingene på :-)

mvh
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 17:12 #40
Nej, ked af det Buzzz...men det blev sent...og jeg ville gerne give points inden jeg gik i seng...jeg skal nok sørge for at du får nogle points næste gang muligheden opstår...hvad den helt sikkert gør...
Avatar billede Syska Mester
07. januar 2011 - 17:34 #41
Helt fint ...

Generics er vejen frem ... i hvert fald mange steder.
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 21:09 #42
Et venligt tip Buzzz...skift billedet ud...det er nemmere at tage dig seriøst, når du ikke har det billede, der bedst egner sig til facebook....

<:o)
Avatar billede Syska Mester
07. januar 2011 - 21:43 #43
Bliver brugt mange steder da de henter det fra gravatar ...

Men ja ... har overvejet det, men orker ikke at skifte det ud. Man skal ikke altid se proff ud, så er det nemmere at give folk "wow" effekten, når der rent faktisk kommer noget intelligent u daf mig :-)

mvh
Avatar billede CodingJoe Nybegynder
07. januar 2011 - 22:25 #44
Jeg oplever desværre den modsatte effekt...jeg har svært ved at tage vedkommende alvorligt...og det vedkommende siger, bliver desværre farvet af det...desværre ingen wow effekt. Desuden behøver en wow effekt ikke have et billede.

Har du det godt med det...så beholder du bare billedet...men bare et venligt tip...
Avatar billede Syska Mester
07. januar 2011 - 23:02 #45
Desværre andres problem, hvis de bliver farvet af et billede og det er jeg bestemt ikke i tvivl om du gør. Man bare læse dette spørgsmål igennem for at finde de svinere du smider efter mig :-).

Men verden er også lille, og nu er det sket to gange på 3 år.

mvh
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester