Laden...
Avatar #avatar-3052.gif
Spontifixus myCSharp.de - Member
Software-Entwickler, Rettungsassistent Hannover Dabei seit 06.09.2005 360 Beiträge
Benutzerbeschreibung

Forenbeiträge von Spontifixus Ingesamt 360 Beiträge

29.10.2011 - 00:56 Uhr

@herbivore: Die Idee ist gut - und bereits altbewährt: Google macht genau das im großen Stil mit recaptcha...

13.09.2011 - 11:20 Uhr

Eben in einem Unit-Test entdeckt (der ansonsten durchaus brauchbare Sachen testet):


[TestMethod]
public void SomeTestMethod(){

    var some = TestCode();

    // TODO:
    // Verify other interesting stuff...

}

08.08.2011 - 17:07 Uhr

Hallo Sebastian,

danke für den Hinweis, ich hab das wie von dir vorgeschlagen über Copy'n'Paste (CSV-Daten in die Zwischenablage kopieren und dann in den entsprechenden Bereich kopieren) gelöst. Das funktioniert extrem schnell.

Viele Grüße,
Markus 😃

27.07.2011 - 09:35 Uhr

Du solltest die Farbe in einen double-Wert umwandeln (siehe Beitrag von Sebastian weiter oben) bevor du sie zuweist...

Gruß,
Markus

07.07.2011 - 10:07 Uhr

Moin moin,

Privat:*Eine Bibliotheksverwaltung für die Schulbücherei (das war vor etwa 12 Jahren mit VB 4... 😉 ) *Jede Menge kleine Programme - manche mehr, die meisten weniger nützlich *Aktuell bastle ich wenn ich Lust und Zeit hab an einem Stellwerk für meine Modellbahn. An diesem Scenario probiere ich eine Menge aus - und fange auch des öfteren mal ganz von vorne an. Unten ein Screenshot aus einer der Applikationen.

Beruflich:*Leitstandsapplikationen für den ÖPNV (Kameraüberwachung, Notrufabfrage, Passenger-Information) *Home Automation *Mobile Anwendungen für Logistikdienstleister

Viele Grüße,
Markus 😃

27.06.2011 - 16:18 Uhr

Hallo Sebastian,

coole API - ich brauche sie gerade wieder für ein kleines Projekt. Vielen Dank dafür!

Und (wie könnte es anders sein) dazu gleich eine Frage. Ich muss mit meinem Programm große Datenmengen (>50.000 Zeilen, 6 Spalten) in Excel importieren. Wenn ich die händisch (Zelle für Zelle) hinzufüge dauert das ewig.
Gibt es eine Möglichkeit das zu beschleunigen, beispielsweise über einen CSV-Import?

EDIT: Da habe ich wohl nicht klar genug formuliert. Die Frage bezieht sich ganz konkret auf die netoffice-API: Ist ein CSV-Import mit dieser API möglich? Und wenn ja, wie?

Viele Grüße,
Markus 😃

06.06.2011 - 16:23 Uhr

Ich kann aus eigener Erfahrung sagen, dass die PrepKits von uCertify (kostenpflichtig) recht gut auf die Prüfung vorbereiten.
Es gibt noch eine schweizer Seite (testmaster.ch) bei der man kostenlos soviele Tests (unter anderem für die 70-511) machen kann wie man möchte. Dort kostet jeder absolvierte Test 2 sog. Testpunkte. Man startet mit 10 Punkten und kann sein Konto durch das bewerten von Fragen nach dem Test wieder auffüllen. Diese Seite ist ganz nützlich, aber die Fragen liegen vom Niveau her oft deutlich unter dem tatsächlichen Prüfungsniveau.

Viele Grüße und viel Erfolg,
Markus 😃

17.05.2011 - 17:26 Uhr

Ich glaub, du übertreibst 😉 So wie die meisten Band Seiten ausschauen, sind die an einem Tag mit Notepad zusammengeschustert. Das ist auch in etwa der Aufwand, mit dem ich rechnen würde. Selbstverständlich, wenn alle Inhalte fertig geliefert werden, und dann noch zusätzlich Tests/Nachbesserungen. Aber das ist jetzt ziemlich sicher kein großes Projekt, wo man ein CMS braucht.

Du hast natürlich recht, wenn es um ein paar zusammengeschusterte Notepad-Seiten geht und es auch dabei bleibt.

Aber nicht selten kommt dann "Wir hätten gerne ein Gästebuch" oder "Wir möchten selber Eintragen können wenn wir einen Gig haben" und dann ist man mit einem System wie Wordpress besser bedient - denn erstens kann das schon ne ganze Menge, und zweitens gibts für das was Wordpress nicht direkt kann Plugins...

Nachtrag: Und auch für eine in Notepad zusammengeschusterte Seite braucht man (wenn sie ein bisschen ordentlich aussehen soll) zwei Tage...

17.05.2011 - 08:52 Uhr

Auch wenn ich im beruflichen Bereich deutlich teurer bin, baue ich doch Webseiten für die bucklige Verwandtschaft oder Freunde für 15 bis 20 Euro / Stunde.

Wenn du eine einfache (!) Webseite rechnest (z.B. ein Wordpress-System mit einem Design-Template, dass du nicht verändern musst und ohne die Entwicklung von eigenen Plugins) kannst du mit etwa 24 bis 32 Std. rechnen bis die Webseite so läuft, dass der Kunde zufrieden ist. Wenn du noch Grafiken bauen musst, kommen nochmal mindestens zwei Tage (16 Std.) dazu.
Die Zahlen gelten natürlich nur, wenn du den Inhalt der Webseite (die Texte, Hörproben etc...) nicht selber machen musst. Sonst kommen dafür auch nochmal um die zwei Tage (16 Std.) dazu.

Wenn du die Webseite komplett selber baust (ohne auf ein bestehendes CMS aufzusetzen) wage ich nicht den Aufwand abzuschätzen...

Ich würde an deiner Stelle von einem Festpreis abraten, und die Webseite für deine Freunde entweder umsonst oder zu einem festen Stundensatz basteln. Lass dich für ein solches Projekt nicht auf einen Festpreis ein - es sei denn du willst diesen Fehler unbedingt mal gemacht haben... 😉

Viele Grüße,
Markus 😃

13.05.2011 - 14:54 Uhr

Hallo Maddinel,

der Salt wird zusammen mit dem Gehashten Passwort in der Tabelle gespeichert. Der Sinn eines Salzes ist es ja die Anwendung von Rainbow-Tables unmöglich zu machen. Der Datenbankeindringling würde immer noch nahezu ewig brauchen für jeden Salt (!) eine neue Rainbow-Table berechnen zu müssen - selbst wenn er die Salts kennt.

Gruß,
Markus 😃

PS: Und die Brute-Force-Attacke EDIT nach herbivores Beitrag: funktioniert nicht, weil du beim Login auf der Seite oder im System ja immer noch einen Salt anhängst... wird dadurch auch nicht weniger aufwändig als ohne Salt.

07.04.2011 - 12:32 Uhr

Moin,

Noch eine Anmerkung zu deiner Überschreibung:

public override string Text {
    get { return base.Text; }
    set { base.Text = value; }
}

Damit hast du nichts gewonnen, denn du überschreibst den Code zwar, greifst aber trotzdem auf die Implementierung der Basisklasse zurück - da kannst du dir das überschreiben auch sparen.

Einen eigenen (unveränderlichen) Text erreichst du folgendermaßen:

public override string Text {
    get { return "Mein Text" }
    set { }
}

Die Thematik Properties und Methoden zu überschreiben gehört allerdings zu den Grundlagen des Programmierens mit C# und dem .NET-Framework...

Viele Grüße,
Markus 😃

01.04.2011 - 14:26 Uhr

Ahhhhh - Schon die nummer Zwei auf die ich heute reinfalle.

@Team: Herzlichen Glückwunsch - genial gemachte Vereimerung! So müssen Aprilscherze sein!

Viele Grüße,
Markus 😃

01.04.2011 - 09:22 Uhr

Interessante Idee.

Wenn aber sowieso alle Beiträge von Moderatoren freigegeben werden - warum dann nicht den Thread offen lassen und die Beiträge manuell moderieren?

Es fühlt sich weniger hart an, wenn es heißt "Dein Beitrag wird moderiert" als wenn es heißt "Der Thread wurde automatisch geschlossen"...

(EDIT: Weiter unten habe ich den Gedanken weitergedacht...)

Könnt ihr sicherstellen, dass wenigstens einigermaßen rund um die Uhr jemand da ist, der auf neue Beiträge kontrolliert? Es mag zwar in der Nacht ein paar Stunden geben wo niemand ernsthaft auf eine Antwort wartet, aber ich kann mir gut vorstellen, dass Hobbyprogrammierer (und Studentden 😉 SCNR - ich war selbst einer) insbesondere in den Abendstunden so zwischen 19:00 und Mitternacht aktiv sind. Gibts da Statistiken drüber?

Das Team ist zwar relativ groß, aber ich könnte mir doch vorstellen, dass es zu Situationen kommt wo durch einen zufall für eine oder zwei Stunden keiner von Euch Moderatoren online ist. Bleiben dann Beiträge auf Halde liegen?

Je mehr ich darüber nachdenke desto weniger gefällt mir diese Idee. Dieses Forum war schon immer sehr gut moderiert, und ich empfindes dieses Forum als eines der angenehmsten in denen ich lese bzw. schreibe.
Trotzdem denke ich dass diese Maßnahme ein wenig Overkill ist - denn diese Maßnahme trifft in erster Linie die Nutzer die brauchbare Fragen stellen und sich an ernsthaften Diskussionen beteiligen.

Wäre es zur Verhinderung von Grundlagenfragen nicht sinnvoller nur neue Threads zu moderieren und diese erst von einem Moderator freigeben zu lassen bevor sie auf der Webseite erscheinen? So kämen solche Threads erst gar nicht auf, und der normale User wäre trotzdem nicht in seiner Teilnahme eingeschränkt.

Viele Grüße,
Markus 😃

21.03.2011 - 17:27 Uhr

Moin,

soweit ich das weiß kommt erst mit der Standard-Edition das Search-Feature mit dazu, in der Enterprise-Version dann inkl. FAST.

Informationen zum "Search"-Feature von SharePoint gibts bei sharepoint.microsoft.com/... (auch wenn du den wahrscheinlich schon kennst)

Viele Grüße,
Markus 😃

15.03.2011 - 14:34 Uhr

Hallo bSharp,

auch deine Lösung erzielt den gewünschten Effekt, aber hält sich nicht ganz an die Aufgabenstellung. Allerdings hat deine Lösung auch was - denn wer vermutet schon, dass sich hinter einem String nicht ein System.String verbirgt...

Dann stelle ich hier mal meine Lösung vor. Die Ursprungsklasse wird (wie von zommi bereits vorgeschlagen) um das keyword partial ergänzt.

static partial class Program {

    [STAThread]
    static void Main(string[] args) {

        if (args.Length == 0 || args[0] == string.Empty) {
            Console.WriteLine("Bitte geben Sie den Namen des Angestellten an, den Sie feuern möchten!");
            return;
        }

        // Jede
        // Menge
        // Code
        // um
        // den
        // Angestellten
        // loszuwerden
        // ...

    }

}

Die andere Hälfte der Klasse Program, die wir dem Programm unterschieben enthält (wie von zommi vorgeschlagen) einen Typinitialisierer - denn nur der wird in diesem Beispiel vor der Methode Main ausgeführt.

Aber worin liegt nun die Magie die die Überprüfung in der originalen Main-Methode ein unerwartetes Ergebnis liefern lässt? Der gewünschte Effekt lässt sich mit einer einzigen Zeile voll Schabernack erzielen:

static partial class Program {

    static Program()  {
        typeof(string).GetField("Empty").SetValue(null, "Ihr Name");
    }

}

Da zommi an der Aufgabenstellung am nächsten dran war darf er weitermachen! 😃

Ich muss allerdings gestehen, dass ich nicht von ganz allein auf diese Aufgabenstellung gekommen bin: The Daily WTF: The Disgruntled Bomb (in den Kommentaren findet sich die Anregung...)

Viele Grüße,
Markus 😃

15.03.2011 - 09:38 Uhr

Hallo zommi,

der Trick mit dem partial-keyword und dem Typinitialisierer war gefragt. Allerdings kommt mein Typinitialisierer mit einer einzigen Zeile Code aus - ohne sich dabei auf die Kommandozeilenparameter zu beziehen 😉
Ich werd nochmal ein Weilchen warten und ansonsten meinen Code posten...

@AndereAnsätze: Egal was dabei rauskommt: bis jetzt ist zommi der erste der sich tatsächlich an die Aufgabenstellung gehalten hat. (Eine versteckte Datei in der Solution)...

Viele Grüße,
Markus 😃

14.03.2011 - 19:46 Uhr

Hallo zusammen,

da der letzte Beitrag ja schon eine kleine Ewigkeit her ist, erlaube ich mir mal ein neues kleines Rätsel zu stellen. Ich formuliere die Frage mal so, wie sie bei einer Zertifizierungsprüfung gestellt würde. 😉

Sie arbeiten als Software-Enwickler bei der Firma Kleine Klitsche GBR und verwenden Visual Studio 2010 mit .NET 4 als Entwicklungsumgebung.

Trotz exzellenter Leistungen erhalten Sie die Kündigung. Sie haben durch Zufall erfahren, dass der Chef bei Kündigungen immer ein kleines Konsolenprogramm aufruft, um sämtliche Daten des Gekündigten aus dem System zu entfernen.

Bevor der Chef Sie jedoch aus dem Büro geleitet, bekommt er einen Anruf und lässt Sie für ein paar Minuten an Ihrem Platz allein. Schnell starten Sie Visual Studio und laden die Solution der kleinen Applikation. Damit ihre Änderung so unauffällig wie möglich bleibt, fügen Sie der Originaldatei nur ein einziges Wort hinzu. Allerdings verstecken Sie eine weitere Datei in den Tiefen der kleinen Applikation.

Gerade als Sie Ihre "Arbeit" abgeschlossen haben erscheint Ihr Gerade-Noch-Chef und geleitet Sie aus dem Büro. Kaum das er Sie vor die Tür gesetzt hat verschwindet der Jetzt-Ex-Chef in seinem Kämmerlein. Sie spitzen die Ohren und richtig: Keine zwei Minuten später hören Sie ein ersticktes Schluchzen aus eben diesem Kämmerlein und machen sich fröhlich pfeifend auf den Weg zum Arbeitsamt...

Was war geschehen? Jedes mal wenn der Zum-Glück-Nicht-Mehr-Chef der kleinen Applikation Ihren Namen übergibt erscheint derselbe Text auf dem Bildschirm:

[TT]c:\>KollegenKicker.exe "Ihr Name"
Bitte geben Sie den Namen des Angestellten an, den Sie feuern möchten!
c:\>
[/TT]

So sah das Programm vor Ihrer Änderung aus:

static class Program {

    [STAThread]
    static void Main(string[] args) {

        if (args.Length == 0 || args[0] == string.Empty) {
            Console.WriteLine("Bitte geben Sie den Namen des Angestellten an, den Sie feuern möchten!");
            return; 
        }

        // Jede 
        // Menge
        // Code
        // um
        // den
        // Angestellten
        // loszuwerden
        // ...

    }

}

Welches Wort fügen Sie in die Datei Program.cs ein, und welche Datei erstellen Sie noch um den gewünschten Effekt zu erreichen?

Es gewinnt die Antwort, die mit dem wenigsten Code auskommt!

25.02.2011 - 15:35 Uhr

Gestern in einem unserer Projekte entdeckt: Der sog. throw-catch Block!


public void DoSomething() {
    try {
        throw new NotSupportedException("Methode wird nicht unterstützt.");
    
        // Etliche
        // Zeilen
        // auskommentierter
        // Sourcecode

    } catch {
    }
}
24.01.2011 - 15:42 Uhr

... zumal die Beschreibung des Forums eindeutig ist: "Diskussionen zu allen sonstigen Themen"

06.01.2011 - 19:08 Uhr

Dass man Fenster an den Rand (oder nach oben) schieben kann, habe ich auch jeden Tag verwendet - aber dass das über Tasten geht war mir neu (auch wenn ich mir das hätte denken können...)

06.01.2011 - 18:51 Uhr

Moin,

habt ihr mal versucht wenn ihr mehrere Windows auf habt eins davon mit der Maus zu "schütteln"? Oder bei einem Fenster die Tastenkombination <Windows><Links> oder <Windows><Rechts> ausprobiert?

Ich bin begeistert!

Viele Grüße,
Markus 😃

06.01.2011 - 16:45 Uhr

Hallo Qt21580,

dann hatte ich dich richtig verstanden. Ein Formular auf diese Weise zu laden ist nicht unbedingt der beste Weg.
Du könntest dem Formular einen Konstruktor geben, der einen boolschen Parameter übernimmt anhand dem festestellt wird ob die EventHandler ausgeführt werden oder nicht. (Also eine Art "DesignMode")

Ich nehme an du baust die Applikation mit Windows-Forms? Dann schau dir mal das MVP (Model-View-Presenter) Pattern an. Wenn du die relevante Logik in einen Presenter auslagerst, kannst du den View (in dem Fall deine Form) je nach Anzeigegrund mit einen passenden Presenter anzeigen. Im Falle eines normalen Applikationsstarts ist das eben der der die Produktivdaten bereitstellt, im Falle des Rechteeditor tut er nichts außer die Form anzeigen und vielleicht Dummy-Daten bereitstellen.

Viele Grüße,
Markus 😃

06.01.2011 - 16:12 Uhr

Hallo Qt21580,

das ganze sieht noch etwas unausgegoren aus. Ich habe da noch ein paar Fragen. Warum erstellst du eine neue Instanz von dem gewünschten Typ? Wo registrierst du dich auf die Events von denen du dich deregistrieren willst - bzw. welche Handler willst du deregistrieren?

13.12.2010 - 09:35 Uhr

Moin moin,

ich kann dir noch das Forum TSSF empfehlen - die beschäftigen sich mit nix anderem als Eisenbahnsimulationen...

Viele Grüße,
Markus 😃

10.12.2010 - 14:34 Uhr

... in diesem Fall der System.Threading.Timer, dem man mitgeben kann wann er den TimerCallback aufrufen soll...

Viele Grüße,
Markus 😃

10.12.2010 - 09:03 Uhr

2 Fragen warum:

  
 EventHandler createMenu = CreateMenu;  
  

Dieses Konstrukt ist eine Frage der Thread-Safety. Folgendes Konstrukt ist nicht Thread-Safe, da nach der Prüfung ob EventHandler registriert sind auch wieder welche deregistiert werden können bevor der Handler aufgerufen wird. In diesem Fall würde der direkte Auftruf von CreateMenu in einer NullReferenceException resultieren:

if(CreateMenu != null) {
    // <-- hier könnte sich in einem anderen Thread der letzte Handler deregistrieren
    CreateMenu(this, EventArgs.Empty);
}

Durch den Umweg über eine lokale Variable wird diese Situation entschärft, da die Prüfung auf der lokalen Variable ausgeführt wird, die sich nicht verändert - auch wenn ein EventHandler deregiestriert wird.


var handler = CreateMenu;
// <-- selbst wenn sich jetzt der letzte Handler von CreateMenu deregistriert
//     ist hat das keinen Einfluss mehr auf die lokale Variable handler.
if(handler != null) {
    handler(this, EventArgs.Empty);
}

Viele Grüße,
Markus 😃

10.12.2010 - 08:56 Uhr

9000end
10000end

Interessante Schreibweise. Sprich Neuntausendend oder Zehntausendend 😉 SCNR....

edit: Typos gefixt. Bitte keinem verraten, dass ein Beitrag weiter noch der falsche Text steht...

10.12.2010 - 08:26 Uhr

Moin,

Danke für die Antwort. Sicherlich habe ich ein RootItem - die in meinem vorangegangenen Beitrag sind nur ein kleiner Ausschnitt aus dem XML- oder dem dazugehörigen C#-Code. Es geht nicht darum wie deserialisiere ich überhaupt irgendwas - sondern wie deserialisiere ich ein bool...

Aber nach einer Nacht drüber schlafen bin ich selbst drauf gekommen.

<TestItem IstIrgendwas="True" />

Diese Schreibweise funktioniert nicht, denn der Serializer arbeitet Case-Sensitiv.

<TestItem IstIrgendwas="true" />

Diese Schreibweise wird anstandslos deserialisiert...

Viele Grüße,
Markus 😃

09.12.2010 - 18:02 Uhr

Hallo zusammen,

ich habe eine XML-Datenstruktur, die ich deserialisieren möchte. Darin z.B. folgendes Item:

<TestItem IstIrgendwas="True" />

Dazu hatte ich folgenden Code implementiert:

[XmlAttribute]
public bool IstIrgendwas{ get; set; }

Das funktioniert so natürlich nicht, da der Wert "True" ein string ist. Kann ich das eleganter lösen als eine String- und eine boolsche Property zu definieren, so dass der String "True" direkt in einen boolschen Wert deserialisiert wird?

Wenn ich dem XmlAttribute-Attribute den Typ System.Bool mitgebe funktioniert das auch nicht wie gewünscht...

Viele Grüße,
Markus 😃

02.12.2010 - 15:48 Uhr

Hallo Sebastian,

vielen Dank für die Umsetzung!

Viele Grüße,
Markus 😃

30.11.2010 - 12:44 Uhr

Wie meine vorredner bereits anmerken kann ich im .NET-Framework keiner zwingen irgendwo try/catch-Blöcke zu verwenden - auch nicht wenn du mit Dateien umgehst.

Was du vielleicht meinst sind "Exception Contracts" so wie in Java...

public int DivideNull(int x, int y) throws DivideByZeroException
{
    return x / y;
}

...allerdings ist das wie gesagt Java - und nicht C# oder .NET.

Viele Grüße,
Markus 😃

25.11.2010 - 11:07 Uhr

Hallo nochmal,

ich komme nicht drumrum mich nochmal zu melden. Ich versuche bei Zellen den Hintergrund zu entfernen (In Excel wäre das "No Fill"). Das kann ich aber über die Interior.Color-Eigenschaft nicht erreichen, denn sogar wenn ich Color.Transparent angebe füllt er die Zelle weiß.
Möglich sein müsste das mit der Interior.ColorIndex-Eigenschaft, dem man dann die Konstante XlColorIndex.xlColorIndexNone übergeben kann...

Und dann möchte ich gerne Zeilen gruppieren (so dass vorne ein [+] oder ein * zum Auf- oder Zuklappen steht. Das sollte (wenn man diversen Google-Funden glauben darf [klick]) die Methode Range.Group erledigen. Auch wenn ich aus der hier verlinkten Doku nicht schlau werde...

Finale Frage: Kannst du diese Dinge noch einbauen?

Viele Grüße,
Markus 😃

25.11.2010 - 08:45 Uhr

Hallo Sebastian,

schläfst du nicht? =)
Ganz herzlichen Dank für die schnelle Antwort und den Fix des Problems!

Viele Grüße aus Hannover,
Markus 🙂

24.11.2010 - 18:45 Uhr

Hallo Sebastian,

erstmal vielen Dank für die Entwicklung dieser API!

Trotzdem habe ich eine Frage, die ich auch in den mitgelieferten Beispielen nicht beantwortet finde. Wie kann ich in meinem Exceldokument eine Zeile an einem bestimmten Index hinzufügen?

Viele Grüße,
Markus 😃

22.11.2010 - 13:32 Uhr

Soweit ich weiß musst du von 2 auf 3.5 und dann von 3.5 auf 4 upgraden. Wie weiter oben geschrieben solltest du aber im MCP-Portal (auf das du ja wegen deiner schon vorhandenen Zertifizierungen zugreifen kannst) dir die Zertifizierungspfade zur gewünschten Zertifizierung anzeigen lassen können.

Viele Grüße,
Markus 😃

22.11.2010 - 11:03 Uhr

Projektverwaltung mit Tickets bzw Bugrequests und Wiki machen wir mit Redmine 😃

Bugrequest - was ein cooles Wort - das Analogon wäre dann der Featurereport (auch als "Bedienungsanleitung" bekannt) 😉

04.11.2010 - 14:13 Uhr

Moin,

ich hatte ein ähnliches Problem bei einer Kartendarstellung, wo bestimmte Punkte und Texte auf der Karte nicht mitskalieren sollten. Ich habe denen ebenfalls ein ScaleTransform zugewiesen und den Faktor auf 1/ScaleFaktorVomParent gesetzt (also den Zoom umgekehrt). Damit blieben die Element gleich groß.

Da man diese Eigenschaften leider nicht Databinden kann, habe ich das über eine Helperklasse gelöst...

Gruß,
Markus 😃

02.11.2010 - 09:50 Uhr

Bob Muglia hat da nochmal ein paar Dinge klargestellt bzw. konkretisiert: PDC and Silverlight

29.10.2010 - 11:31 Uhr

Weil es trotzdem bedingt hier reingehört - auch wenn es nicht das ist war wir uns wünschen, sondern das was Microsoft ungeachtet dessen macht 😉

Microsoft hat auf der PDC bekanntgegeben wo der Hauptfokus der Weiterentwicklung von C# und VB liegen wird: heise.de: PDC: Asynchrone Zukunft bei C# 5.0 und Visual Basic 11.0

27.10.2010 - 09:17 Uhr

Das ist eine einfache Frage.

Du hast jetzt die Grundlagen und die alte ASP.NET 2.0 Prüfung. Du brauchst also um bis zum 2.0er Enterprise MCPD zu kommen noch 2 MCTS-Prüfungen und eine MCPD-Prüfung. Anschließend kannst du mit zwei weritern Prüfungen zum 4.0 MCPD upgraden. Insgesamt also noch 5 Prüfungen.

Um direkt zum 4.0er MCPD (Web Applications, Enterprise gibts nicht mehr) bräuchtest du jetzt insgesamt noch 4 Prüfungen (Web-Applications, Communication, DataAccess MCTS) und die 4.0er MCPD-Prüfung.

Da ist es relativ einfach den Weg zu bestimmen. Du kannst aber im MCP-Portal bei MS auch angeben welches Zertifikat du erreichen Willst und das Portal berechnet mögliche Wege ausgehend von deinen bisherigen Zertifikaten.

Und dann wählst du den Weg des geringsten Widerstands 😉

Viele Grüße,
Markus 😃

22.10.2010 - 10:48 Uhr

Moin moin,

wenn die bisherige Aufgabe nicht gelöst wurde, kann nach bisherigen Regeln dieses Threads jeder eine neue Aufgabe stellen.

Die Lösung für meine Aufgabe wäre ein 14 Zeilen langer XAML-Schnipsel gewesen:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="Editor">
                <MenuItem Command="Undo" />
                <MenuItem Command="Redo" />
                <MenuItem Command="Cut" />
                <MenuItem Command="Copy" />
                <MenuItem Command="Paste" />
            </MenuItem>
        </Menu>
        <RichTextBox />
    </DockPanel>
</Window>

Wenn talla eine Aufgabe hat - darf er aber gerne weitermachen 😉

Viele Grüße,
Markus 😃

15.10.2010 - 14:51 Uhr

Die nächste Aufgabe braucht keine Logik - und zwar im wahrsten Sinne des Wortes:
Erstelle einen kleinen Texteditor ausschließlich in XAML. Für den Editor sind folgende Anforderungen definiert:
1.Der Editor besteht aus genau einem Fenster 1.Der Editor hat direkt unter dem Fenstertitel eine Menüleiste mit einem Menü beschriftet mit "Editor". Darin Menüpunkte Rückgängig, Wiederherstellen, Kopieren, Ausschneiden und Einfügen, die jeweils auch über die Windows-üblichen Tastenkürzel ansprechbar sein müssen und in der jeweils eingestellten Sprache des Betriebssystems beschriftet sein sollen. Zusätzlich sollen die Tastenkürzel im Menü angezeigt werden. Die Menüpunkte dürfen nur aktiviert werden, wenn die entsprechende Aktion verfügbar ist. 1.Der Editor verfügt über einen Eingabebereich für den Text, der den gesamten Rest des Fensters einnimmt.

Der Code zur Lösung ist nicht als Dateianhang, sondern inline im Beitrag zu posten. Es gilt je kürzer desto besser - Trotzdem sollte das XAML natürlich wie üblich formatiert sein.

EDIT: Natürlich darf das C#-Projekt weitere notwendige Dateien wie z.B. die App.xaml enthalten.

Viel Spaß 😃

15.10.2010 - 14:07 Uhr

Hier ist sie nun die Lösung - auch wenn der Gehirnschmalz dahinter nicht von mir kommt, die Implementierung ist von mir. 😉

Damit wir im weiteren Verlauf einfach und übersichtlich arbeiten können brauchen wir zwei kleine Extras. Zum einen eine Extension-Method die aus einer IEnumerable von IGroupings wieder eine flache Liste macht:

public static class Extensions {
    
    public static List<TOut> ToFlatList<TOut>(this IEnumerable<IGrouping<int, TOut>> grouping) {

        var newList = new List<TOut>();
        foreach (var group in grouping)
            newList.AddRange(group);
        return newList;

    }

}

Als nächstes brauchen wir noch eine Datenstruktur die Zahlenpaare sowie deren Produkte, Summen und Differenzen halten kann:

private struct CalculationInfo {

    public int X;
    public int Y;

    public int Product;
    public int Sum;
    public int Difference;

    public override string ToString() {
        return string.Format("CalculationInfo: X={0}, Y={1}, Product={2}, Sum={3}, Difference={4}", X, Y, Product, Sum, Difference);
    }

}

Bis hierhin war's einfach. 😁

Für die Lösung des Rätsels brauchen wir eine Liste mit den Faktoren und Summanden. Sowohl Multiplikation als auch Addition sind Kommutativ (Das Zahlenpaar (X,Y) ist für die Lösung der Aufgabe identisch zum Paar (Y,X)). Zwar ist die Subtraktion nicht kommutativ, trotzdem kann man aufgrund der Aufgabenstellung davon ausgehen, dass der Betrag der Differenz interessant ist, denn Daniela erwähnt nichts von einer positiven oder negativen Zahl. Von daher können wir um unnötigen Rechenaufwand zu vermeiden für die Lösung auf Zahlenpaare zurückgreifen, bei denen die zweite Zahl größer oder gleich der ersten ist.

var workingList = new List<CalculationInfo>();
for (var x = 1; x <= 1000; x++)
    for (var y = x; y <= 1000; y++)
            workingList.Add(new CalculationInfo {
                X = x,
                Y = y,
                Product = x * y,
                Sum = x + y,
                Difference = Math.Abs(x - y)
            });

Berta sagt zu den anderen: "Ich kann die Lösung nicht nennen".
Was verannlasst Berta zu dieser Aussage? Antonia hat Berta das Produkt zweier Zahlen genannt. Wäre das Produkt kleiner als Tausend und eine Primzahl, dann würde Berta die Lösung kennen, denn dann kämen nur zwei Zahlen in Betracht: Die eins und das Produkt selber.
Berta würde die Lösung ebenfalls kennen, wenn die genannte Zahl größer als 1000 und das Produkt zweier Primzahlen wäre - denn dann würde die Lösung mit der eins nicht mehr greifen.
Die Zahl 5055 zum Beispiel ist in der Primfaktorenzerlegung 3 x 5 x 337. Soll das Produkt durch zwei Zahlen im Bereich von 1 bis 1000 dargestellt werden geht das nur als 15 x 337, denn sowohl bei 3 x 1685 als auch bei 5 x 1011 ist der zweite Faktor größer als 1000.
Wirklich aussagekräftig ist die Aussage von Berta also nicht, denn wir haben ja schon festgestellt, dass wir mit Primzahlen nicht weiterkommen.
Was wir aber wissen, ist, dass das Produkt, das Antonia Berta zugeflüstert hat mehrfach vorkommen muss, denn ansonsten wüsste Berta ja bereits was die Lösung wäre.
Diese Erkenntnis könnten wir jetzt ausnutzen um die Menge der verfügbaren Zahlenpaare einzugrenzen - tun wir aber nicht.

Christina antwortet: "Das wusste ich 😄"
Da scheint sich Christina ja ganz schön sicher zu sein. Dieser Hinweis ist - nunja - herausfordernd platziert. Den Christina wusste eigentlich schon von Anfang an, dass Berta die Lösung nicht kennen kann.
Was heißt das genau? Christina sieht eine Zahl, die man nur so aus zwei Summanden zusammensetzen kann, dass für alle Paare der Summanden gilt was zuvor bereits gesagt wurde. Kennt Christina zum Beispiel die Zahl 18, könnte die Lösung 1 + 17 sein. 17 ist allerdings eine Primzahl und deswegen könnte Berta die Lösung kennen. Also könnte im Falle der 18 Christina nicht schon vorher wissen das Berta die Lösung nicht kennt. Damit scheidet die 18 aus, und mit ihr alle Paare von Zahlen die addiert 18 ergeben.
Was lernen wir? Die Information das Christina weiß, dass Berta die Lösung nicht kennt ist viel Wertvoller als das Geständnis von Berta keine Ahnung zu haben.
Wir können jetzt aus unserer Arbeitsliste alle die Datensätze streichen bei denen eine oder mehrere Kombinationen von Summanden existieren mit denen man bei Kenntnis des Produktes auf die Lösung kommen würde.
Im Klartext heißt das: Wir suchen alle eindeutigen Produkte aus der Arbeitsliste, holen uns die dazugehörigen Summen und entfernen anschließend alle Werte mit diesen Summen aus der Arbeitsliste. Im Code sieht das dann so aus:

var sumsByUniqueProducts = workingList.GroupBy(value => value.Product)
                                      .Where(item => item.Count() == 1)
                                      .ToFlatList()
                                      .GroupBy(value => value.Sum)
                                      .Select(value => value.Key)
                                      .ToArray();
workingList = workingList.Where(workingItem => !sumsByUniqueProducts.Contains(workingItem.Sum)).ToList();

Damit enthält die Worklist jetzt statt 500500 nur noch 27596 Einträge.

Darauf Berta: "Dann weiß ich jetzt die Lösung."
Dieser Hinweis ist deutlich einfacher auszuwerten als die vorhergehenden. Wir wissen jetzt, dass das Produkt der gesuchten Zahlen nur noch einmal in der Arbeitsliste vorkommt. Das wiederum erlaubt es uns alle einträge aus der Arbeitsliste zu entfernen, deren Produkt mehr als einmal in der Liste auftaucht.

workingList = workingList.GroupBy(value => value.Product)
                         .Where(item => item.Count() == 1)
                         .ToFlatList();

Die Arbeitsliste enthält jetzt noch 6984 Einträge.

Christina entgegnet: "Dann weiß ich sie jetzt auch."
Dieser Hinweis enthält eine ähnliche Annahme wie der vorangegangene von Berta. Nur das sich die Annahme hier auf die Summen und nicht auf die Produkte bezieht. Wir können also damit Fortfahren alle Einträge aus der Liste zu entfernen deren Summe mehr als einmal in der Liste auftaucht.

workingList = workingList.GroupBy(value => value.Sum)
                         .Where(item => item.Count() == 1)
                         .ToFlatList();

Jetzt bleiben noch niedliche 27 EInträge übrig.

Daniela sagt: "Ich nicht, aber ich habe eine Vermutung, was eine der beiden Zahlen wahrscheinlich ist."
Aus diesem Hinweis kann man zwei Schlussfolgerungen ziehen. Einerseits weist er darauf hin, dass in der Menge der Zahlenpaare aus denen man Danielas Differenz bilden könnte ein Wert häufiger vorhanden ist als andere.
Es gibt allerdings noch eine weitere Schlussfolgerung: Danielas Differenz ist in der Arbeitstabelle mehr als einmal vorhanden, denn sonst wüsste Sie das Ergebnis ja jetzt auch.
Genau genommen müssen für die infragekommende Differenz mehr als zwei Einträge vorhanden sein, denn sonst kann nicht einer der Werte häufiger vorhanden sein als alle anderen.

workingList = workingList.GroupBy(value => value.Difference)
                         .Where(item => item.Count() > 2)
                         .ToFlatList();

Unsere Arbeitsliste enthält jetzt noch genau 6 Einträge.

Berta sagt: "Ich weiß, was du vermutest, aber das ist falsch."
Von so einer Aussage lässt sich Daniela allerdings nicht unterkriegen. Wir wissen jetzt dass einer der Werte bei zwei Datensätzen der Arbeitsliste auftauchen muss. Das Ergebnis dieser Datensätze ist also die Differenz. Dazu zählen wir die Datensätze bei denen der doppelte Wert vorkommt und entfernen anschließend alle Datensätze die die dort berechnete Differenz nicht enthalten aus der Arbeitsliste.

var occurrences = new Dictionary<int, int>();
foreach (var difference in workingList) {
    if (!occurrences.ContainsKey(difference.X))
        occurrences.Add(difference.X, 0);
    occurrences[difference.X]++;
    if (!occurrences.ContainsKey(difference.Y))
        occurrences.Add(difference.Y, 0);
    occurrences[difference.Y]++;
}
var wrongNumber = occurrences.Where(item => item.Value == occurrences.Values.Max())
                             .First()
                             .Key;
workingList = workingList.Where(item => item.X != wrongNumber && 
                                        item.Y != wrongNumber)
                         .ToList();

Wir erhalten eine Liste mit drei Werten. Jetzt ist auch Daniela stolz wie Oskar:

Daniela: "Dann kenne ich jetzt auch die Lösung."
Jetzt weiß auch Daniela dass ihre Differenz in der Arbeitsliste nur noch ein einziges Mal enthalten ist und kann so die überflüssigen Datensätze ausschließen:

workingList = workingList.GroupBy(value => value.Difference)
                         .Where(item => item.Count() == 1)
                         .ToFlatList();

Und endlich, endlich kennen auch wir den gesuchten Datensatz:

CalculationInfo: X=64, Y=73, Product=4672, Sum=137, Difference=9

Den Code habe ich nochmal als kompilierbare Datei an diesen Beitrag angehängt. Vielen Dank an fairymail.de für die Denkarbeit hinter der Lösung 😉

15.10.2010 - 08:36 Uhr

Moin,

ich hab lange nachgedacht und bin zu keinem Ergebnis gekommen und hab schließlich gegoogelt. Das Ding ist tatsächlich mit einigem Hirnschmalz und ein paar Zeilen Code zu lösen. Faszinierend... 😃

Viele Grüße,
Markus 😃

13.10.2010 - 13:42 Uhr

Moin moin,

Bevor ich mir hier die Finger wundtippe verweise ich auf die Übersicht was man wofür braucht bei microsoft.com/learning

Viele Grüße,
Markus 😃

12.10.2010 - 19:12 Uhr

Hallo gfoidl,

da ich gerade ein bisschen auf der Leitung stehe habe ich mal recherchiert.
In diesem Dokument (Seite 9) steht eine geringfügig abweichende Definition von "geschlossen" und "offen".

Wäre dem so - würde folgende Implementierung der Klasse PolygonzugAufgabe Ausreichen:

public class PolygonzugAufgabe {
    public bool IstOffen(IEnumerable<Punkt> punkte)
    {
        return !punkte.Last().Equals(punkte.First());            
    }
}

Die Klassen für die Strecke, sowie die Extension-Methode wären dann nicht mehr nötig.

In deiner Aufgabenstellung geht es aber darum, das von den Strecken des Polygonzuges mindestens eine Fläche komplett umschlossen wird - auch wenn das Polygon selber (gemäß der o.g. Definition) als offen zu bezeichnen ist?

Viele Grüße,
Markus 😃

12.10.2010 - 18:22 Uhr

Mir ist gerade aufgefallen, dass laut Steigung eine parallele zur y-Achse nicht als Funktionsgraph gilt, die Steigung aber als Unendlich angesehen werden kann. Dann funktioniert natürlich meine Rechnung nicht mehr.
Ich hatte gehofft meine Lösung noch aufbohren zu können aber für Strecken parallel zur y-Achse taugt die wohl nichts...

Das hier beschriebene Steigungsproblem lässt aber den Hinweis von gfoidl unberührt - selbst wenn ich das Quadrat auf die Spitze stelle wird es nicht als geschlossen erkannt.

Lange Rede kurzer Sinn: Der hier vorgestellte Ansatz ist hervorragend als Exponat für das Museum der krankhaften Ideen auf Maximegalon geeignet, aber nicht als Lösungsansatz, der die von gfoidl gestellten Kriterien erfüllt.

Ich bin gespannt auf die Lösung!

12.10.2010 - 17:30 Uhr

Stimmt auffallend. Werde ich noch korrigieren.

12.10.2010 - 16:29 Uhr

Moin,

zur Lösung der Aufgabe von gfoidl brauche ich folgendes:

Eine Extension-Method die berechnet ob sich ein double-Wert in einem bestimmten Bereich findet:

public static class Extenstions
{
    public static bool IsBetween(this double value, double border1, double border2) {
        if (border1 < border2) return (value >= border1 && value <= border2);
        if (border1 > border2) return (value >= border2 && value <= border1);
        return value == border1;
    }
}

Dann einen Struct der einen Punkt darstellt:

public struct Punkt {
    
    public double X;
    public double Y;

    public Punkt(double x, double y) {
        X = x;
        Y = y;
    }
    
    public override bool Equals(object obj) {
        if (!(obj is Punkt)) return false;
        var andererPunkt = (Punkt)obj;
        return (X.Equals(andererPunkt.X) && Y.Equals(andererPunkt.Y));
    }

}

Einen Struct der eine Strecke abbildet und der Methoden enthält mit denen festgestellt werden kann ob eine Strecke eine andere schneidet oder ein direkter Nachbar einer anderen Strecke ist:

public struct Strecke {

    public Punkt P1;
    public Punkt P2;
    public double M;
    public double C;

    public Strecke(Punkt p1, Punkt p2) {
        P1 = p1;
        P2 = p2;
            
        // Steigung und Y-Achsenabschnitt berechnen
        M = (P2.Y - P1.Y) / (P2.X - P1.X);
        C = P1.Y - (M * P1.X);
        }

    public bool Schneidet(Strecke andereStrecke) {
        
        // X-Wert des Schnittpunktes berechnen und feststellen ob
        // der Punkt innerhalb der definierten Strecken liegt
        var schnittpunkt = (andereStrecke.C - C) / (M - andereStrecke.M);

        // Wenn sich für den Schnittpunkt gar nicht erst ein gültiger Wert
        // ergibt wird es wohl keinen geben
        if (double.IsInfinity(schnittpunkt) || double.IsNaN(schnittpunkt)) return false;

        // Wenn es einen Wert gibt muss geprüft werden ob er innerhalb einer
        // der angegeben Strecken liegt
        return schnittpunkt.IsBetween(P1.X, P2.X) &&  
               schnittpunkt.IsBetween(andereStrecke.P1.X, andereStrecke.P2.X);
    }

    public bool IstNachbar(Strecke andereStrecke) {
        return (P1.Equals(andereStrecke.P1) || P1.Equals(andereStrecke.P2)) || 
               (P2.Equals(andereStrecke.P1) || P2.Equals(andereStrecke.P2));
    }

    public override bool Equals(object obj) {
        if (!(obj is Strecke)) return false;
        var andereLinie = (Strecke)obj;
        return (P1.Equals(andereLinie.P1) && P2.Equals(andereLinie.P2));
    }

}

Und last but not least die von gfoidl vorgegebene Klasse die die Logik zur Überprüfung der einzelnen Polygonzüge enthält:


public class PolygonzugAufgabe {

    private readonly List<Strecke> _linien = new List<Strecke>();

    public bool IstOffen(IEnumerable<Punkt> punkte) {
        var punkteArray = punkte.ToArray();
        for (var i = 0; i < punkte.Count() - 1; i++)
            _linien.Add(new Strecke(punkteArray[i], punkteArray[i + 1]));

        return _linien.All(linie1 => !_linien.Any(linie2 => !linie1.IstNachbar(linie2) && 
                                                            !linie1.Equals(linie2) &&
                                                            linie1.Schneidet(linie2)));
    }

}

Das ganze in einen Kochtopf, kompilieren, testen, fertig. Ist vielleicht nicht immer unbedingt die eleganteste Lösung - aber sie funktioniert. 😃