Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C#] Van procedureel naar OOP - Globale data en arrays

Pagina: 1
Acties:

  • Consequator
  • Registratie: Juli 2000
  • Laatst online: 13-10 14:55
Ik ben bezig mezelf hobbymatig C# aan te leren na jaren op dezelfde manier met procedureel php te hebben gewerkt.(niet op web server maar als console programma)
Ik heb het OOP nog niet echt tussen de oren maar als fun start project heb ik mij voorgenomen om een simpele second life (ja dat bestaat nog =p) bot te maken en daar langzaam op voort te borduren.
(op dezelfde manier heb ik PHP ook geleerd, maar dan procedureel ;))

Met PHP had ik een hoop $globalvar[$localvar1][$lvar2][$lvar3] achtige constructies om met dynamische data om te gaan vanuit verschillende functies m.b.v. foreach zonder steeds MySQL queries te hoven te doen. (vluchtige 'runtime' data)

Simpel data voorbeeld:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[users] => Array (
    [active] => Array (
        [user1] => Array (
            [Naam] = "Plop1"
            [...] = ...
        )
        [user3] => Array (
            [Naam] = "Plop3"
            [...] = ...
        )
    )
    [inactive] => Array (
        [user2] => Array (
            [Naam] = "Plop2"
            [...] = ...
        )
    )
    [...] => etc
)


Ik had al begrepen dat globale variabelen een doodzonde zijn met C# en multimensionele arrays schijnen ook lastig te zijn.
Dus mijn vraag, wat is de beste manier om dit fatsoenlijk op te pakken :-)

Mijn doel is dat ik iets heb waar ik gegevens in kan zetten die vanuit meerdere plekken in het programma zijn op te vragen.
In dit specifieke geval gaat het om een lijst met personen die op dit moment worden gezien of die recentelijk gezien zijn, hier wil ik dan vanuit andere events dingen uit lezen en wijzigen.
De data structuur hierboven is ook niet een must, een lijst met gebruikers + data en een lijst met wie actief of inactief is kan natuurlijk ook.
Met PHP had ik b.v. ook een globale var waar mysql tabel namen in stonden zodat ik verkorte namen kon gebruiken of eventueel zelfs een hele tabel kon hernoemen zonder het hele script door te hoeven.

Ik heb nog geen idee hoe ik MySQL er in krijg voor externe data dus ik houd het eerst bij alleen lokale data om 1 probleem tegelijk te tackelen ;)

Als iemand nog goeie tips heeft voor beginnend C# literatuur dan houd ik mij ook aanbevolen, ik zat al in het boeken topic te sneupen maar daar loop ik wat tegen het bomen & bos probleem aan. Vooral het stukje 'wanneer gebruik ik wat' is voor mij nog een probleem.

  • The_Ghost16
  • Registratie: Januari 2004
  • Laatst online: 28-10 14:26
In principe zou je in C# gewoon een lijst van users kunnen hebben. Zoiets als List<User>(). Op de User entiteit kun je een property hebben die aangeeft of een gebruiker actief of inactief is. Een Active property van het type boolean of.

Hiermee kun je dmv LINQ queries heel makkelijk de actieve en inactieve users krijgen.
Iets als:
users.Where(u=>u.Active) en users.Where(u=>!u.Active)

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
The_Ghost16 schreef op dinsdag 03 september 2013 @ 15:11:
In principe zou je in C# gewoon een lijst van users kunnen hebben. Zoiets als List<User>(). Op de User entiteit kun je een property hebben die aangeeft of een gebruiker actief of inactief is. Een Active property van het type boolean of.

Hiermee kun je dmv LINQ queries heel makkelijk de actieve en inactieve users krijgen.
Iets als:
users.Where(u=>u.Active) en users.Where(u=>!u.Active)
Gebruik dan liever een Dictionary<string, User>, dan zijn je lookups tenminste O(1).
Consequator schreef op dinsdag 03 september 2013 @ 15:04:
Ik had al begrepen dat globale variabelen een doodzonde zijn
Mwa; nogal afhankelijk van de context (zoals altijd). In een simpele program.cs met verder weinig meer dan een handvol regels code is 't andere koek dan in een meerlaags project. Er is zoveel "doodzonde" en 't is nogal afhankelijk van naar wie je luister. Goto is ook doodzonde, evenals Singletons en ga zo maar door. Ja, in principe wel. In de praktijk zijn er (soms goed, soms minder goed te verdedigen) uitzonderingen.
Consequator schreef op dinsdag 03 september 2013 @ 15:04:
met C# en multimensionele arrays schijnen ook lastig te zijn.
Wie heeft je dat verteld? Nul probleem hoor. Maar waar je wél van af moet is denken in simpele arrays waar je "zomaar vanalles in frot". In C# zul je veel eerder een List<T>, Dictionary<T> o.i.d. hebben met typed objecten (zoals het type User) met ieder z'n eigen properties/methods etc. Dan doe je dus niet meer $myusers['jantje']['foo']['lastlogin'] (en dan maar hopen dat die elementen allemaal bestaan :P ) maar myusers["jantje"].Foo.LastLogin (nadat je hebt gekeken of de key 'jantje' in je dictionary voorkomt ;) ).

[ Voor 7% gewijzigd door RobIII op 03-09-2013 16:40 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • 4Real
  • Registratie: Juni 2001
  • Laatst online: 14-09-2024
Als er wordt gezegd dat globals een doodzonde is. Hoe moet ik dan de connection string van een database opslaan? Want daar heb ik altijd moeite mee om die netjes weg te programmeren. De programma's die ik programmeer (hobby) hebben allemaal een één-op-één relatie met een database, dus kan ik gerust gebruik maken van een Singleton database class, maar wat nou als ik twee databases ga gebruiken? Hoe moet ik dan met de connectionstrings omgaan, aangezien ik dan de Sql classes beter wil verwerken.

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
4Real schreef op woensdag 04 september 2013 @ 09:43:
Als er wordt gezegd dat globals een doodzonde is. Hoe moet ik dan de connection string van een database opslaan? Want daar heb ik altijd moeite mee om die netjes weg te programmeren.
Gewoon in de config file, en dan gebruik maken van MSDN: ConfigurationManager.ConnectionStrings Property (System.Configuration)
De programma's die ik programmeer (hobby) hebben allemaal een één-op-één relatie met een database, dus kan ik gerust gebruik maken van een Singleton database class, maar wat nou als ik twee databases ga gebruiken? Hoe moet ik dan met de connectionstrings omgaan, aangezien ik dan de Sql classes beter wil verwerken.
Dat er een 1-op-1 relatie met de database is maakt nog niet dat het handig is om een Singleton database class te maken, terwijl het natuurlijk prima voor kan komen dat er uiteindelijk maar 1 instance van je database class is ( Hoewel het afhankelijk is wat die class precies doet, want het is meestal niet handig om alles via 1 connectie te laten lopen ). Een van de grote problemen van een Singleton is de hoge mate van afhankelijkheid van je code.

“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.”


  • Consequator
  • Registratie: Juli 2000
  • Laatst online: 13-10 14:55
RobIII schreef op dinsdag 03 september 2013 @ 16:37:

Wie heeft je dat verteld? Nul probleem hoor. Maar waar je wél van af moet is denken in simpele arrays waar je "zomaar vanalles in frot". In C# zul je veel eerder een List<T>, Dictionary<T> o.i.d. hebben met typed objecten (zoals het type User) met ieder z'n eigen properties/methods etc. Dan doe je dus niet meer $myusers['jantje']['foo']['lastlogin'] (en dan maar hopen dat die elementen allemaal bestaan :P ) maar myusers["jantje"].Foo.LastLogin (nadat je hebt gekeken of de key 'jantje' in je dictionary voorkomt ;) ).
Ik ga mij even verdiepen in dictionaries en lists :-)

Met 'zomaar vanalles in frot' bedoel je dat vooraf gedefinieerd moet zijn wat er precies in gaat komen en wat voor soort data dat is ?
Met PHP ga ik meestal met een foreach door de array heen dus dan weet ik zeker dat het er is, ik heb mezelf aangeleerd om met het voor het eerst setten van gebruiker gelijk een array standaard waarden wordt neergezet. Dat scheelde een hoop if isset ;)

Mijn 'doodzondes' kwamen van observaties na google-fu bij vragen waar ik tegenaan liep, maar als die observaties fout zijn des te beter :)

SQL komt later nog wel eens.
1 stap tegelijk anders gaan we 8)7

Iedereen bedankt, dit zal vast niet de laatste keer zijn dat ik Het kwartje om in OOP te denken moet bij mij ook nog vallen ;)

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 22:23

Creepy

Tactical Espionage Splatterer

Hmja, wil je nu OOP gaan denken of niet? Zo nee, ombouwen met dictionaries en lists en gaan. Zo ja, dan ook echt OOP gaan denken en iets een een User class introduceren waarin je kan vragen of ie active is of niet (i.p.v. twee lijsten active en inactive bij te gaan houden).

Ook in PHP is het aan te raden om niet zomaar alles in arrays (maps eigenlijk) te gooien. Je kan namelijk alles in een map gooien. Dus als je ergens user['name'] gebruikt i.p.v. user['naam'] gaat niets je zomaar op die fout wijzen. Met een User class die een getNaam() heeft is het dus onmogelijk om getName() aan te roepen en krijg je gelijk een foutmelding voor je neus. (Nog even los van het feit dat naam beter name had kunnen zijn om zo het gros van de naamgeving in 1 taal te hebben...

[ Voor 12% gewijzigd door Creepy op 04-09-2013 12:11 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Consequator
  • Registratie: Juli 2000
  • Laatst online: 13-10 14:55
Creepy schreef op woensdag 04 september 2013 @ 12:10:
Hmja, wil je nu OOP gaan denken of niet? Zo nee, ombouwen met dictionaries en lists en gaan. Zo ja, dan ook echt OOP gaan denken en iets een een User class introduceren waarin je kan vragen of ie active is of niet (i.p.v. twee lijsten active en inactive bij te gaan houden).

Ook in PHP is het aan te raden om niet zomaar alles in arrays (maps eigenlijk) te gooien. Je kan namelijk alles in een map gooien. Dus als je ergens user['name'] gebruikt i.p.v. user['naam'] gaat niets je zomaar op die fout wijzen. Met een User class die een getNaam() heeft is het dus onmogelijk om getName() aan te roepen en krijg je gelijk een foutmelding voor je neus. (Nog even los van het feit dat naam beter name had kunnen zijn om zo het gros van de naamgeving in 1 taal te hebben...
Ik doe het langzaam aan, eerst maar eens half om half :P
Werken met arrays in php heb ik gelukkig wel aardig onder de knie, ik houd wel altijd een vaste structuur aan. Dit zal hopelijk een plus zijn met het switchen naar C#. Het is alleen makkelijk om tijdens het uitbreiden extra dingen toe te voegen aan een array in php met lang lopende projectjes.
Meestal programmeer ik in het Engels, zelfs met comments. ik had alleen voor het voorbeeld iets in het Nederlands bedacht ;)

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class User {
  public int Id { get; set; }
  public string Username { get; set; }
  public bool IsActive { get; set; }
  public DateTime RegistrationDate { get; set; }
  public string FavoriteColor { get; set; }
}

var myusers = new List<User>();

// ...fill list here... (**)

var activeusersthatfancyred = myusers
    .Where(u => u.IsActive && u.FavoriteColor.Equals("Red"))
    .OrderBy(u => u.RegistrationDate);


Probeer dat maar eens met PHP*. Wil je "tijdens het uitbreiden extra dingen toe [...] voegen" dan voeg je een property aan User toe et voila.

* Let op: hieronder komt een smartypants betweter een manier om dit in PHP voor elkaar te prutsen posten :+

** :
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
myusers.Add(new User()
{
    Id = 123,
    Username = "RobII",
    IsActive = true,
    RegistrationDate = new DateTime(2001,12,18, 21,33 ,0),
    FavoriteColor = "Blue"
});
myusers.Add(new User()
{
...
}
myusers.Add(new User()
{
...
}

//...Of, nog mooier:

var myusers = new List<User>(new[] {
    new User()
    {
        Id = 123,
        Username = "RobII",
        IsActive = true,
        RegistrationDate = new DateTime(2001,12,18, 21,33 ,0),
        FavoriteColor = "Blue"
    }, new User()
    {
        ...
    }, new User()
    {
        ...
    }
});

^ Maar normaal haal je dat uit een DB of file of whatever natuurlijk.

C#:
1
2
3
4
5
var userlookup = myusers.ToDictionary(u => u.Id);
var hi_my_name_is = userlookup[123].Username;   //Slim shady!
//Of:
var userlookup = myusers.ToDictionary(u => u.Username);
var favcolor = userlookup["RobIII"].FavoriteColor;

[ Voor 49% gewijzigd door RobIII op 04-09-2013 22:23 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • PatrickH89
  • Registratie: November 2009
  • Laatst online: 17:24
RobIII schreef op woensdag 04 september 2013 @ 22:09:

* Let op: hieronder komt een smartypants betweter een manier om dit in PHP voor elkaar te prutsen posten :+
Want dat zijn natuurlijk geen basis OOP elementen die niet ook gewoon in PHP zitten :+

Met uitzondering van Lists en Dictionaries natuurlijk, maar in PHP hebben array's natuurlijk gewoon dezelfde functionaliteit (los van welke implementatie beter is).

[ Voor 21% gewijzigd door PatrickH89 op 04-09-2013 22:33 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
PatrickH89 schreef op woensdag 04 september 2013 @ 22:31:
Want dat zijn natuurlijk geen basis OOP elementen die niet ook gewoon in PHP zitten :+
Ik doelde vooral op 't niet hoeven frotten met arrays ($users['foo']['bar']['baz']) en strong-typing ;) (en LINQ en lists en dictionaries en extension methods en... O+ )

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Styxxy
  • Registratie: Augustus 2009
  • Laatst online: 17:52
RobIII schreef op woensdag 04 september 2013 @ 22:43:
[...]
Ik doelde vooral op 't niet hoeven frotten met arrays ($users['foo']['bar']['baz']) en strong-typing ;) (en LINQ en lists en dictionaries en extension methods en... O+ )
Persoonlijk zou ik een beginner in .NET net zo ver mogelijk van LINQ willen houden. Laat hem eerst de basis van OOP (en .NET) onder de knie krijgen vooraleer hij wat fancy gaat doen met LINQ zaken. Dit laatste zorgt vaker voor slechtere code dan goede (dus LINQ dumpen op iemand die eigenlijk nog niet goed weet waar hij mee bezig is => platform).

Al bij al heb ik het gevoel dat een goede cursus OOP veel beter op z'n plaats is hier, dan wat specifieke "fancy" zaken van .NET hier rond te strooien.

  • Consequator
  • Registratie: Juli 2000
  • Laatst online: 13-10 14:55
RobIII schreef op woensdag 04 september 2013 @ 22:09:
[code=c#]
public class User {
~snip~snip~
Hier ben je mij even kwijt..
Je maakt een public class aan met een serie variabelen en hun data type.
Hierna declareer je een variabele met die class als 'data type'
Dan heb je een enkel 'array' waar Id/Username etc als waarden in kunnen worden gezet.
En die kan je weer in een dictionary/list hangen zodat je een lijst kan maken waar onder elke key de waarden van die public class hangen ?

Hoe kan ik vervolgens die waarden raadplegen op andere plekken om b.v. te kijken of hij al bestaat ?
Ik zit al wat te experimenteren maar ik kom niet bij de waarden.

Dit is wat ik ongeveer heb, met alle events,text commando's en andere brul er uit gefilterd om het overzichtelijker te maken.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace TestBot
{
    public class User
    {
        public UUID uuid { get; set; }
        public string name { get; set; }
        public string realname { get; set; }
    }
    class TestBotMain
    {
        private static string input;
        static void Main(string[] args)
        {
            var usertrack = new List<User>();
            while (!quit) {
                      input = Console.Readline();
            }
        }
       static void doe_iets(object sender, ietsargs e)
       {
               <hier checken of b.v. $usertrack[user1][uuid] bestaat>
       }
}

  • sopsop
  • Registratie: Januari 2002
  • Laatst online: 20-11 13:38

sopsop

[v] [;,,;] [v]

Je hebt je variabele usertrack binnen de main functie gezet, daardoor is de scope van deze variabele beperkt tot de main functie.

Als je deze op dezelfde plek declareert als de input variabele is hij wel beschikbaar in je doeiets functie.

En daar kun je dan je check op doen, bijvoorbeeld:

C#:
1
2
3
4
private bool doe_iets(object sender, ietsargs e)
{ 
return usertrack.Any(u => u.Name == name));
}
Pagina: 1