Laden...

For Loop mit Abzweigung

Erstellt von Silentwolf vor einem Jahr Letzter Beitrag vor einem Jahr 504 Views
S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr
For Loop mit Abzweigung

Hallo,

ich bin noch etwas neu mit C# Programmierung und auch hier im Forum.
Gerade würde ich für meine Arbeit folgendes gerne Programmieren.
Ich möchte zwischen zwei Datum die Werktage und auch Sonn und Feiertage zählen und diese in einer Win Form txtWorkDays die Anzahl der Werktage ohne Sonn und Feiertage ausgeben.
Und in txtSundays die Anzahl der enthaltenen Sonn und Feiertage.
Im Moment habe ich es nur mit zwei verschiedenen Methoden geschafft aber würde eine einzelne Methode gern verwenden und hier bekomme ich einen Fehler.

TestAmount(DateTime, DateTime); not all code paths return a value.

Könnte jemand mir diesbezüglich bitte helfen wie dieser Code geändert werden müsste?

public partial class DayCalculator : Form
  {
    public DayCalculator()
    {
      InitializeComponent();
    }
    private void btnOk_Click(object sender, EventArgs e)
    {
      DateTime dateStart = dtpStart.Value.Date;
      DateTime dateEnd = dtpEnd.Value.Date;

      txtWorkDays.Text = WorkDaysAmount(dateStart, dateEnd).ToString();
      txtSundays.Text = HolidaysAmount(dateStart, dateEnd).ToString();

    }
public int TestAmount(DateTime dtpStart, DateTime dtpEnd)
    {
      List<DateTime> holiday = new List<DateTime>();
      holiday.Add(new DateTime(DateTime.Now.Year, 1, 1));
      holiday.Add(new DateTime(DateTime.Now.Year, 1, 6));
      holiday.Add(new DateTime(DateTime.Now.Year, 3, 19));
      holiday.Add(new DateTime(DateTime.Now.Year, 4, 15));
      holiday.Add(new DateTime(DateTime.Now.Year, 5, 1));
      holiday.Add(new DateTime(DateTime.Now.Year, 5, 26));
      holiday.Add(new DateTime(DateTime.Now.Year, 6, 6));

      int wdays = 0;
      int hdays = 0;
      for (DateTime date = dtpStart; date <= dtpEnd; date = date.AddDays(1))
      {
        if (dtpStart.DayOfWeek != DayOfWeek.Sunday && !holiday.Contains(date))
        {
          wdays++;
          dtpStart = dtpStart.AddDays(1);
          return wdays;
        }
        if (dtpStart.DayOfWeek == DayOfWeek.Sunday || holiday.Contains(date))
        {
          hdays++;
          dtpStart = dtpStart.AddDays(1);
          return hdays;
        }
      }
    }
  }

Hoffe ich habe alles richtig gemacht mit dem Posten?

Recht vielen Dank

Albert

16.830 Beiträge seit 2008
vor einem Jahr

Der Methode TestAmount fehlt die Rückgabe.
Du hast zwar zwei returns in den if-conditions - aber wenn beide if-conditions nicht anschlagen, dann hast Du keinen return => Syntaxfehler.
Alle Fälle einer Methode müssen eine Rückgabe haben (abgesehen von void etc..).

PS, für Dich einfach als Hinweis: [FAQ] DateTime vs. DateTimeOffset und der Umgang mit Zeiten in .NET

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Hallo Abt,

Danke für Deine Antwort.
Wo müsst ich denn diesen einfügen?

Tut mir leid stehe noch ein wenig auf dem Schlauch mit C# oops.

16.830 Beiträge seit 2008
vor einem Jahr

Spätestens am Ende der Methode musst irgendwas zurück geben.

4.938 Beiträge seit 2008
vor einem Jahr

Außerdem solltest du dir die Logik der gesamten Schleife nochmal überdenken:

  • durch die beiden return-Anweisungen ist die jeweilige Zeile vorher überflüssig
  • da die zweite Bedingung die Negation der ersten ist, reicht ein else dort
  • daher wird bisher immer bei Schleifenstart die Methode sofort verlassen, anstatt die weiteren Datumswerte zu überprüfen

Am besten, du schreibst dafür einige Unit-Tests: [Artikel] Unit-Tests: Einführung in das Unit-Testing mit VisualStudio

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Ok ich werde es versuchen )
So habe ich es nun erstellt die Fehlermeldung is weg, aber das Resultat bzw. die Resultate stimmen leider nicht.

Wahrscheinlich muss das eine andere Variables sein oder?

public int TestAmount(DateTime dtpStart, DateTime dtpEnd)
    {
      List<DateTime> holiday = new List<DateTime>();
      holiday.Add(new DateTime(DateTime.Now.Year, 1, 1));
      holiday.Add(new DateTime(DateTime.Now.Year, 1, 6));
      holiday.Add(new DateTime(DateTime.Now.Year, 3, 19));
      holiday.Add(new DateTime(DateTime.Now.Year, 4, 15));
      holiday.Add(new DateTime(DateTime.Now.Year, 5, 1));
      holiday.Add(new DateTime(DateTime.Now.Year, 5, 26));
      holiday.Add(new DateTime(DateTime.Now.Year, 6, 6));

      int wdays = 0;
      int hdays = 0;
      for (DateTime date = dtpStart; date <= dtpEnd; date = date.AddDays(1))
      {
        if (dtpStart.DayOfWeek != DayOfWeek.Sunday && !holiday.Contains(date))
        {
          wdays++;
          dtpStart = dtpStart.AddDays(1);
          return wdays;
        }
        if (dtpStart.DayOfWeek == DayOfWeek.Sunday || holiday.Contains(date))
        {
          hdays++;
          dtpStart = dtpStart.AddDays(1);
          return hdays;
        }        
      }
      return hdays;
    }
  }

P.S Danke für Den Beitrag werde ich mir dann noch genau ansehen!

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Hallo,

Danke für Deinen Beitrag!
Und den link ich werde es mir ansehen!

Ja wie gesagt leider noch ziehmlich neu auf dem Gebiet muss ich noch sehr viel darüber lernen.

Danke auf alle Fälle für die Tipps und Beiträge!

16.830 Beiträge seit 2008
vor einem Jahr

Mir is die gewünschte Logik unklar.

Du verweist auf zwei Methoden, die für uns nicht ersichtlich sind.


      txtWorkDays.Text = WorkDaysAmount(dateStart, dateEnd).ToString();
      txtSundays.Text = HolidaysAmount(dateStart, dateEnd).ToString();

Dafür wird Deine Methode TestAmount nirgends aufgerufen.

Was soll das denn werden? Eine Methode, die beide Werte zurück liefert?
Aktuell liefert sie ja nur einen Wert und von Außen kannst eigentlich nicht erkennen, welchen.

3.825 Beiträge seit 2006
vor einem Jahr

Auch in der Methode TestAmount stimmt die Logik nicht. Du gibst immer eine 1 zurück. Du willst aber sicher die Anzahl der Tage wissen.

Das könnte so aussehen :


public int HolidaysAmount(DateTime dtpStart, DateTime dtpEnd)
{
    int hdays = 0;
    List<DateTime> holiday = HolidayDays();
    for (DateTime date = dtpStart; date ≤ dtpEnd; date = date.AddDays(1))
        if (dtpStart.DayOfWeek == DayOfWeek.Sunday || holiday.Contains(date))
            hdays++;
    return hdays;
}

Du brauchst 2 Methoden weil Du ja 2 Werte berechnen willst. Oder Du nutzt eine Methode und übergibst die Werte per ref.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Oh tut mir leid Abt,

das war vorher als ich noch zwei Methoden hatte und ich mit Copy und Paste leider einen Fehler gemacht habe!!
Tut mir leid!

Soll natürlich nun nur noch eine Methode sein

txtWorkDays.Text = TestAmount(dateStart, dateEnd).ToString();
      txtSundays.Text = TestAmount(dateStart, dateEnd).ToString();
16.830 Beiträge seit 2008
vor einem Jahr

Naja, aber so wird das niemals funktionieren.
Wenn Du einer Methode immer die gleichen Werte gibst, woher soll die Methode wissen ob sie Dir Workdays oder Sundays zurück geben soll.
Du musst also a) zwei Methode haben oder b) die Methode muss beide Werte zurück geben, zB über eine Hilfsklasse.

Verstehe dass Du neu bist, aber das sind Grundlagen, die man in den ersten 4 Schulstunden lernt 😉
Also pack Dich ran an ein Tutorial 🙂

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Hallo,

ja ich möchte die Anzahl der Tage wissen.
Habe diesen Code Snippet ein wenig gegoogelt und gefunden leider bin ich noch nicht so sattelfest.

Also wenn ich eine Methode für nur die Sonn und Feiertage verwende hier gezeigt dann funktioniert diese.

public int HolidaysAmount(DateTime dtpStart, DateTime dtpEnd)
    {
      List<DateTime> holiday = new List<DateTime>();
      holiday.Add(new DateTime(DateTime.Now.Year, 1, 1));
      holiday.Add(new DateTime(DateTime.Now.Year, 1, 6));
      holiday.Add(new DateTime(DateTime.Now.Year, 3, 19));
      holiday.Add(new DateTime(DateTime.Now.Year, 4, 15));
      holiday.Add(new DateTime(DateTime.Now.Year, 5, 1));
      holiday.Add(new DateTime(DateTime.Now.Year, 5, 26));
      holiday.Add(new DateTime(DateTime.Now.Year, 6, 6));

      int hdays = 0;

      for (DateTime date = dtpStart; date <= dtpEnd; date = date.AddDays(1))
      {
        if (dtpStart.DayOfWeek == DayOfWeek.Sunday || holiday.Contains(date))
        {
          hdays++;
        }
        dtpStart = dtpStart.AddDays(1);
      }
      return hdays;
    }

und eine weiter habe ich für die Werktage

public int Workdays(DateTime dtpStart, DateTime dtpEnd)
    {
      var dateDiff = ((TimeSpan)(dtpEnd - dtpStart)).TotalDays + 1;
      return (int)dateDiff;
    }
    public int WorkDaysAmount(DateTime dtpStart, DateTime dtpEnd)
    {
      List<DateTime> holiday = new List<DateTime>();
      holiday.Add(new DateTime(DateTime.Now.Year, 1, 1));
      holiday.Add(new DateTime(DateTime.Now.Year, 1, 6));
      holiday.Add(new DateTime(DateTime.Now.Year, 3, 19));
      holiday.Add(new DateTime(DateTime.Now.Year, 4, 15));
      holiday.Add(new DateTime(DateTime.Now.Year, 5, 1));
      holiday.Add(new DateTime(DateTime.Now.Year, 5, 26));
      holiday.Add(new DateTime(DateTime.Now.Year, 6, 6));

      int wdays = 0;

      for (DateTime date = dtpStart; date <= dtpEnd; date = date.AddDays(1))
      {
        if (dtpStart.DayOfWeek != DayOfWeek.Sunday && !holiday.Contains(date))
        {
          wdays++;
        }
        dtpStart = dtpStart.AddDays(1);
      }
      return wdays;
    }

die funktioniert auch aber diese beiden zusammen legen da fehlt es noch..

Hinweis von Abt vor einem Jahr

Bitte die csharp Tags und nicht pre-Tags verwenden 😉
Korrigier ich die ganze Zeit schon.. dachte merkst es irgendwann.

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Ja hast eh recht.

Ich bin eh beim lesen und studieren gg aber das konnte ich noch nicht rausfinden ..)

Aber werde mich schlau machen )

Vielen Dank erstmals!

16.830 Beiträge seit 2008
vor einem Jahr

Du hast nur einen Rückgabetyp "int", dann kannst eben auch nur einen Wert zurück geben.
Du brauchst eine Hilfsklasse, dann kannst mehrere Werte zurück geben.
Das return erfolgt dann ganz am Ende der Methode für beide Werte; nicht mittendrin irgendein return.

Darüber hinaus hast Du durch das Zusammenlegen die Logik vollständig verbogen. Das zweite if kann nicht mehr funktionieren.
Du überschreibst den dtpStart- Wert, sodass für das zweite if die Ausgangslage völlig anders ist.

Also:

  • Logik sauber trennen
  • Hilfsklasse verwenden

C# Grundlagen erlernen 🙂

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Danke Bernd,

werde ich dann auch probieren!
Leider muss ich bald mal los aber werde mich später wieder melden wenn ich Fortschritte gemacht habe.

Vielen lieben Dank an alle!

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Jo das hab ich befürchtet das ich alles drunter und drüber geschmissen habe.

Na gibt viel zu tun )

Danke werde es mir ansehen!

3.825 Beiträge seit 2006
vor einem Jahr

Wenn Du nur eine Methode haben willst, die dann aber zweimal aufgerufen wird geht das auch so :



int wdays = DaysAmount(dtpStart, dtpEnd, false);
int hdays = DaysAmount(dtpStart, dtpEnd, true);

...

public int DaysAmount(DateTime dtpStart, DateTime dtpEnd, bool holidays)
{
    int days = 0;
    List<DateTime> holidaylist = HolidayDays();
    for (DateTime date = dtpStart; date ≤ dtpEnd; date = date.AddDays(1))
    {
        if (holidays && (dtpStart.DayOfWeek == DayOfWeek.Sunday || holidaylist.Contains(date))) days++;
        if (!holidays && dtpStart.DayOfWeek != DayOfWeek.Sunday && !holidaylist.Contains(date)) days++;
    }
    return days;
}

Sehe ich aber keinen so großen Vorteil.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

16.830 Beiträge seit 2008
vor einem Jahr

Also lieber zwei Methoden als so eine Methode mit Schalter-Parameter 😁

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Hallo nochmal,

vielen Dank erstmal für die Hilfe!

Hab folgendes geändert im Originalen Code war ein Fehler:

hab mit zwei Methoden weiter gemacht wie auch empfohlen )


      for (DateTime date = dtpStart; date <= dtpEnd; date = date.AddDays(1))
        if ([b]date[/b].DayOfWeek == DayOfWeek.Sunday || holiday.Contains(date))
          hdays++;
      return hdays;

Bezüglich die Code Tags!
Hab den falschen button immer verwendet dachte Code(Inline) macht es

Jetzt hab ich den richtigen Button!

Die Holiday Liste kann man doch sicher auch seperate anfügen glaub das hätte auch BerndFfm vorgeschlagen..

Hierzu muss ich mich aber noch kümmern wie diese genau aufgerufen werden kann.

Aber es ist schon mal die erste Hürde geschafft )

3.825 Beiträge seit 2006
vor einem Jahr

Sollte auch so gehen :


public int DaysAmount(DateTime dtpStart, DateTime dtpEnd, bool holidays)
{
    int days = 0;
    List<DateTime> holidaylist = HolidayDays();
    for (DateTime date = dtpStart; date ≤ dtpEnd; date = date.AddDays(1))
        if (!holidays && dtpStart.DayOfWeek != DayOfWeek.Sunday && !holidaylist.Contains(date)) days++;
        else days++;
    return days;
}

private List<DateTime> HolidayDays()
{
    List<DateTime> holidaylist = ...
    return holidaylist;
}

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

4.938 Beiträge seit 2008
vor einem Jahr

Sorry Bernd, aber dein Code ergibt genauso wenig Sinn wie der ursprüngliche Code vom OP.

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Hallo,

Danke Bernd,
leider bekomme ich noch einen Fehler im Aufruf der Methode.


txtWorkDays.Text = [b]DaysAmount[/b](dateStart, dateEnd).ToString();


    public int DaysAmount(DateTime dtpStart, DateTime dtpEnd, bool holidays)
    {
      int days = 0;
      List<DateTime> holidaylist = HolidayDays();
      for (DateTime date = dtpStart; date <= dtpEnd; date = date.AddDays(1))
        if (!holidays && dtpStart.DayOfWeek != DayOfWeek.Sunday && !holidaylist.Contains(date)) days++;
        else days++;
      return days;
    }


private List<DateTime> HolidayDays()
    {
      List<DateTime> holidaylist = new List<DateTime>();
      holidaylist.Add(new DateTime(DateTime.Now.Year, 1, 1));
      holidaylist.Add(new DateTime(DateTime.Now.Year, 1, 6));
      holidaylist.Add(new DateTime(DateTime.Now.Year, 3, 19));
      holidaylist.Add(new DateTime(DateTime.Now.Year, 4, 15));
      return holidaylist;
    }

So hätte ich es mal verstanden wie der Code aussehen sollte oder?
Dazu hätte ich noch eine Frage und zwar bekomme ich unter der Roten Line in Visual Studio 2022 keine Hilfe oder Itellicence angezeigt.

Weiß jemand warum das ist? Welche Settings wären da zu ändern?

Schöne Grüße

Albert

O
79 Beiträge seit 2011
vor einem Jahr

Die Meldung des Compilers sollte aussagekräftig genug sein 😉

Falls nicht: Deine Methode DaysAmount erwartet drei Parameter. Und wieviele gibst du tatsächlich mit beim Aufruf ?

3.825 Beiträge seit 2006
vor einem Jahr

Das muss natürlich dann so heißen :


txtWorkDays.Text = DaysAmount(dateStart, dateEnd, false).ToString();
txtHolidayDays.Text = DaysAmount(dateStart, dateEnd, true).ToString();

Vergiss bitte meinen Code von 13:05 Uhr, nimm lieber den vorherigen.

Sinn das alles in eine Methode zu packen macht es dann wenn es mal mehrere Arten von errechneten Werten geben soll.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

S
Silentwolf Themenstarter:in
17 Beiträge seit 2020
vor einem Jahr

Danke Bernd,

werde es dann ausprobieren )

Vielen Dank