Code Verbesserung

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von MichaHo.

    Code Verbesserung

    Hallo,
    wollte hier auch mal einen Code abgeben und fragen, was zu verbessern wäre.
    Erstmal, es geht darum, Termine eines Besprechungsraums abzufragen und zu zeigen ob der Raum zum jetzigen Zeitpunkt frei oder gebucht ist.
    Der Code funktioniert bestens, aber eventuell kann man da noch was verbsssern bevor ich mir eine dll erstelle und an die grafische Oberfläche gehe...
    Hier die Klasse EWSConnect:
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Net;
    5. using Microsoft.Exchange.WebServices.Data;
    6. namespace EWS
    7. {
    8. class EWSConnect
    9. {
    10. //Properties
    11. public string mailBox { get; set; }
    12. public string user { get; set; }
    13. public string pass { get; set; }
    14. public string domain { get; set; }
    15. public DateTime startDate { get; set; }
    16. public DateTime endDate { get; set; }
    17. public int maxItems { get; set; }
    18. public bool IsRoomFree { get; private set; }
    19. //Fields
    20. DateTime timeNow = DateTime.Now;
    21. //Constructor
    22. public EWSConnect(string mailBox, string user, string pass, string domain, DateTime startDate, DateTime endDate, int maxItems)
    23. {
    24. this.mailBox = mailBox;
    25. this.user = user;
    26. this.pass = pass;
    27. this.domain = domain;
    28. this.startDate = startDate;
    29. this.endDate = endDate;
    30. this.maxItems = maxItems;
    31. }
    32. //Function
    33. public FindItemsResults<Appointment> GetAppointments()
    34. {
    35. NetworkCredential netCred = new NetworkCredential(this.user, this.pass, this.domain);
    36. ExchangeVersion exVers = ExchangeVersion.Exchange2013;
    37. ExchangeService exService = new ExchangeService(exVers);
    38. exService.Credentials = netCred;
    39. exService.AutodiscoverUrl(this.mailBox);
    40. CalendarFolder calFolder = CalendarFolder.Bind(exService, WellKnownFolderName.Calendar);
    41. CalendarView calView = new CalendarView(this.startDate, this.endDate, this.maxItems);
    42. calView.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
    43. FindItemsResults<Appointment> appointments = calFolder.FindAppointments(calView);
    44. IEnumerable<Appointment> result = from a in appointments where timeNow >= a.Start && timeNow <= a.End select a;
    45. if (result.Any()) { IsRoomFree = false; } else { IsRoomFree = true; }
    46. return appointments;
    47. }
    48. //Method
    49. public string CheckAllocation(string room)
    50. {
    51. IEnumerable<Appointment> busyResult = from a in GetAppointments() where timeNow >= a.Start && timeNow <= a.End select a;
    52. IEnumerable<Appointment> freeResult = (from a in GetAppointments() where a.Start >= timeNow select a).Take(1);
    53. string message = "";
    54. if (!IsRoomFree)
    55. {
    56. foreach (Appointment a in busyResult)
    57. {
    58. message = $"Der Raum {room} ist belegt, bitte anderen Raum buchen \nGebucht: {a.Start:d}, {a.Start:t} - {a.End:t} Uhr";
    59. }
    60. }
    61. else
    62. {
    63. foreach (Appointment a in freeResult)
    64. {
    65. message = $"Der Raum {room} ist frei und kann gebucht werden. \nNächste Buchung: {a.Start:d}, {a.Start:t} - {a.End:t} Uhr";
    66. }
    67. }
    68. return message;
    69. }
    70. }
    71. }


    der Aufruf erfolgt dann Beispielhaft so:
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. namespace EWS
    3. {
    4. class Program
    5. {
    6. static void Main(string[] args)
    7. {
    8. DateTime dateFrom = DateTime.Now.AddDays(-1);
    9. DateTime dateTo = dateFrom.AddDays(14);
    10. string room = "";
    11. EWSConnect meeting_application = new EWSConnect("MailBox", "UserName", "Password", "Domain",dateFrom, dateTo, 10);
    12. room = "Application Office";
    13. Console.WriteLine(meeting_application.CheckAllocation(room));
    14. EWSConnect meeting_bioCel = new EWSConnect("MailBox", "UserName", "Password", "Domain",dateFrom, dateTo, 10);
    15. room = "BioCel";
    16. Console.WriteLine(meeting_bioCel.CheckAllocation(room));
    17. EWSConnect meeting_aquadyn = new EWSConnect("MailBox", "UserName", "Password", "Domain",dateFrom, dateTo, 10);
    18. room = "Aquadyn";
    19. Console.WriteLine(meeting_aquadyn.CheckAllocation(room));
    20. }
    21. }
    22. }


    die Ausgabe auf der Console sieht so aus:

    Da ich mich in Zukunft mehr mit C# beschäftigen will/muss, wären Eure Kommentare sehr hilfreich...
    Danke Euch
    Gruß Micha
    "Hier könnte Ihre Werbung stehen..."

    MichaHo schrieb:

    C#-Quellcode

    1. if (result.Any()) { IsRoomFree = false; } else { IsRoomFree = true; }

    Das würde ich ehrlich gesagt mit "offenen" Klammern schreiben, also in 8 Zeilen, ist jedoch weder Styleguide noch sonst irgendwas, nur meine eigene Meinung.
    Ansonsten kann man (wenn du auf möglichst Kompaktn Code aus bist) in sämtlichen Kontrollstrukturen (if, for, foreach, etc) einen Einzeiler ohne die Klammern schreiben:

    MichaHo schrieb:

    C#-Quellcode

    1. if (!IsRoomFree)
    2. foreach (Appointment a in busyResult)
    3. message = $"Der Raum {room} ist belegt, bitte anderen Raum buchen \nGebucht: {a.Start:d}, {a.Start:t} - {a.End:t} Uhr";
    4. else
    5. foreach (Appointment a in freeResult)
    6. message = $"Der Raum {room} ist frei und kann gebucht werden. \nNächste Buchung: {a.Start:d}, {a.Start:t} - {a.End:t} Uhr";
    7. return message;

    bzw.

    MichaHo schrieb:

    C#-Quellcode

    1. if (result.Any()) IsRoomFree = false; else IsRoomFree = true;


    Edit: Was würde ich dafür geben mit C#7 arbeiten zu können ;(

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „EaranMaleasi“ ()

    Hi @EaranMaleasi. Danke Dir. Halte meinen Code eigentlich immer gerne Kompakt, die Frage ist, ist das sinnvoll :) beim ersten oben würde ich persönlich sagen ja, da ist ein 1 Zeiler gut, bei der foreach Geschichte ist es glaub sinnvoller über mehr zeilen zu gehen. Wobei man sich wohl für eins entscheiden sollte, oder?

    Noch ne andere Frage: Könnte man dies auch auf mehrere Klassen aufteilen? Ist das sinnvoll? ich denke da werden noch mehr Methoden dabei kommen, wobei eben nur Methoden, also könnte man doch hingehen und ne Klasse Room machen, ne Klasse Appointment und dann ne Klasse Result, Result enthält dann alle Methoden, Appointment eben nur die eine Funktion um die Termine abzuholen und Room enthält nur den Konstruktor um einenn neuen Raum zu definieren...

    Fragen über Fragen...
    "Hier könnte Ihre Werbung stehen..."

    MichaHo schrieb:

    C#-Quellcode

    1. if (result.Any()) { IsRoomFree = false; } else { IsRoomFree = true; }
    What :?:

    C#-Quellcode

    1. IsRoomFree = !result.Any();
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Auch reine Geschmackssache, aber ich persönlich würde bei Deklarationen bei denen Typ direkt ersichtlich ist, z.B. hier

    C#-Quellcode

    1. NetworkCredential netCred = new NetworkCredential(this.user, this.pass, this.domain);
    2. ExchangeVersion exVers = ExchangeVersion.Exchange2013;
    3. ExchangeService exService = new ExchangeService(exVers);

    var benutzen.

    Grüße
    Vainamo
    Wieder reine Geschmackssache, aber ich persönlich finde diese SQL abfragen im Code auch nicht schön. Die gibt es auch nur sehr selten, zumindest keine ich keine Leute die das so machen. Das kann man auch nur mit Linq und Lambda abbilden. Z.B.

    C#-Quellcode

    1. IEnumerable<Appointment> busyResult = from a in GetAppointments() where timeNow >= a.Start && timeNow <= a.End select a;

    müsste doch auch so gehen oder?

    C#-Quellcode

    1. IEnumerable<Appointment> busyResult = GetAppointments().Where(a => timeNow >= a.Start && timeNow <= a.End);
    @Vainamo meinst Du dann so?

    C#-Quellcode

    1. var netCred = new NetworkCredential(this.user, this.pass, this.domain);
    2. var exVers = ExchangeVersion.Exchange2013;
    3. var exService = new ExchangeService(exVers);


    Kannst Du bisschen mehr erklären warum/wann man var benutzen sollte?

    @Bluespide: genau DAS hatte ich krampfhaft versucht aber zum verr.... nicht hinbekommen.... Danke Dir, das sieht um einiges Besser aus und ist für mich vor allem besser lesbar
    "Hier könnte Ihre Werbung stehen..."
    var soll quasi zum schnellen Programmieren beitragen, indem du eben nicht mehr ellenlange Typen austippen musst, sondern eben nur diese drei Buchstaben.
    In Fällen wo du über new neue Objekte von Klassen erstellst, kann man es getrost einsetzen, die Klasse steht ja nach wie vor da.
    Kritisch wirds wenn du ne Factory oder ähnliches hast, und der Typ eben nicht klar ersichtlich ist, da du ne .Create() Funktion hast.
    Anstatt sofort zu sehen welche Klasse dort initialisiert wird, musst du auf IntelliSense warten.

    Meine Meinung:
    Da gerade IntelliSense immer "schlauer" wird was die auswahl der Klasse angeht wenn man gerade Tippt, fällt für mich das Argument der Geschwindigkeit eher Flach, da man oftmals nicht mehr als 4 Buchstaben tippen braucht bis zum Tab. Einziges Argument wäre noch übersichtlichkeit von Code, was ich auch irgendwie verstehe denn UberAwesomeFunctionalityProvider ließt sich halt doch schwerer als var. Dennoch ziehe ich es vor, immer den Typ direkt zu sehen.
    @EaranMaleasi OK, klingt plausibel. Wobei ich solche Kosntrukte

    C#-Quellcode

    1. NetworkCredential networkCredentials = new NetworkCredential(this.user, this.pass, this.domain)
    schon blöd finde :)
    Ich denke ich werd es dann so machen, das ich bei eindeutigen dingen (wie obiges Beispiel) die var deklaration nutze und bei allen anderen eben den richtigen Typ. Mal schauen.

    Bin da noch auf ein anderes Problem bei meinem obigen Code gestoßen.
    Wenn der Besprechungsraum nun von heute 14:00 Uhr bis morgen 16:00 Uhr gebucht wurde, steht in der Gui Gebucht: 15.03.17 14:00 Uhr - 16:00 Uhr somit denken die Leuts dann, das der Raum morghen Früh um 08:00 Uhr wieder frei ist. eigentlich müsst in solch einem Fall da stehen Gebucht: 15.03.17 14:00 Uhr - 16.03.17 16:00 Uhr
    Ich bekomme es aber schlichtweg nicht hin. Dachte ich müsste doch eigentlich nur prüfen ob Start und Ende den gleichen Tag haben... geht aber nicht... hier mein kläglicher Versuch:

    C#-Quellcode

    1. foreach (Appointment a in busyResult)
    2. {
    3. if(a.End.Day != a.Start.Day)
    4. message = $"{room}\nDer Raum ist belegt, bitte anderen Raum buchen. \nGebucht: {a.Start} - {a.End}";
    5. message = $"{room}\nDer Raum ist belegt, bitte anderen Raum buchen. \nGebucht: {a.Start:d}, {a.Start:t} - {a.End:t} Uhr";
    6. }

    Also wenn der Meeting Ende Tag nicht dem Meeting Start Tag entspricht, dann schreibe Datum plus Uhrzeit von Start und Ende, ansonsten ist es der gleiche Tag, da reicht dann Datum + Uhrzeit von bis...
    der Code springt IMMER in den 2. message Baum...
    "Hier könnte Ihre Werbung stehen..."
    @EaranMaleasi japp, jetzt hab ich es auch geschnallt :)
    ich überschreibe ja quasi die Variable message nach dem if wieder....
    weil ich da kein Return drinn habe, hab ich das komplett übersehen.

    Nun funktioniert es.... Dankeschön
    "Hier könnte Ihre Werbung stehen..."
    @MichaHo Ja, so war das gedacht. Hier z.B. eine Erklärung von ReSharper: jetbrains.com/help/resharper/2…rOrType_BuiltInTypes.html
    Wie gesagt, var ist reine geschmackssache aber vor allem in Using Konstrukten oder bei ewig langen Deklarationen bei denen Instanz und Klasse evtl sogar gleich heißen, schafft es einfach Übersichtlichkeit. Zudem kann man auch mal relativ schnell den Typen einer Variable ändern, weil man z.B. doch SHA512 haben möchte.

    C#-Quellcode

    1. SHA256CryptoServiceProvider CryptoServiceProvider = new SHA256CryptoServiceProvider();
    2. // vs
    3. var CryptoServiceProvider = new SHA256CryptoServiceProvider();


    Grüße
    Vainamo
    Hi @Vainamo und @ErfinderDesRades... Danke für Eure Erklärungen. den Link schau ich mir später noch an...
    Ich werds so machen wie oben schon erwähnt, wenn der Typ eindeutig ist nehm ich var, ansonsten eben den Typ....
    Danke
    "Hier könnte Ihre Werbung stehen..."