Laden...
U
Benutzerbeschreibung
Konto auf Wunsch des Benutzers gesperrt

Forenbeiträge von userid4382 Ingesamt 239 Beiträge

20.01.2009 - 13:38 Uhr

Reine Neugierde. 🙂
Es geht, aber ich weiß nicht wie - und das nervt mich einfach. =)

20.01.2009 - 12:42 Uhr

Hallo JuyJuka,
wie man es anstellt daß man einen Konstruktor unterdrücken kann, weiß ich schon. Mir geht es um die Frage, wie bekomme ich es hin daß Intellisense "The Class XYZ has no constructor defined" ausgibt.

19.01.2009 - 18:53 Uhr

Zeigt der Reflector auch Attribute an?

19.01.2009 - 17:08 Uhr

An die pdb hatte ich nicht gedacht... nein das war's auch nicht. Ich habe mir gerade mal die AppDomain-Klasse vom Microsoft-Source-Server geholt und angeschaut. Ich verstehe es nicht. Der Konstruktor ist tatsächlich so wie du es geschildert hast und er besitzt auch keine Attribute. Ich hoffe es geht in Ordnung wenn ich hier ein paar Schnipsel poste.

[ClassInterface(ClassInterfaceType.None)]
    [ComDefaultInterface(typeof(System._AppDomain))]
    [ComVisible(true)]
    public sealed class AppDomain : MarshalByRefObject, _AppDomain, IEvidenceFactory 
    {

... und der Konstruktor:

private AppDomain() {
            throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_Constructor)); 
        } 
19.01.2009 - 16:14 Uhr

Was meinst du mit "fremde Assembly"? Ich habe mal probehalber eine Class Library gebastelt und diese in einem anderen Projekt referenziert. Dort kommt ebenfalls die Meldung "Cannot access private..." bzw. "Cannot access internal...".

19.01.2009 - 14:51 Uhr

Hallo,
in C# wird ja zur Compile-Zeit ein Standardkonstruktor angelegt, wenn man nicht selber einen schreibt. In letzter Zeit begegne ich im .net Framework aber immer öfter Klassen (z.B. AppDomain), wo mir schon zur Designzeit mitgeteilt wird, daß diese keinen Konstruktor hat ("The class 'System.AppDomain' has no constructors defined". Ich wüßte gerne mal, wie man so etwas macht. Über einen private accessor am Konstruktor geht es nicht, denn in diesem Fall meldet Intellisense "Cannot access private constructor 'XYZ' here".

16.01.2009 - 19:21 Uhr

Hallo Rainbird,
ich hatte die Prerequisites an einer falschen Stelle gesucht - dank schlechter Dokumentation. Ich dachte, ich finde sie dort wo sie bei anderen Projekt-Typen üblicherweise sind. Statt dessen muß man über einen Rechtsklick auf das Setup-Projekt, dessen Property-Seite aufrufen. Nachdem ich das raus hatte, stand ich vor dem nächsten Problem: Statt VSTO 2005 (2.0.50727) war dort nur die Version 3 eingetragen. Im Windows SDK war die Version die ich brauchte nicht installiert. Die PIA für Office 2003 fehlten ebenfalls. Nach langer Recherche im Internet bin ich auf den BootStrapper Manifest Generator gestoßen. Damit habe ich die Pakete von Hand in die Prerequisites-Liste bekommen.

19.12.2008 - 12:56 Uhr

Hallo,
ich habe ein Outlook 2003 Addin geschrieben und auf einer Testmaschine installiert. Dort hat sich herausgestellt daß VSTO installiert sein muß, damit die Applikation läuft. Weil ich potenziellen Kunden keinen großen Installationsaufwand zumuten will/darf, möchte ich das VSTO-Paket gerne über die Prerequisites im Setup einbinden - nur leider fehlen ausser "Publish Now" sämtliche Optionen-Buttons! Was nun? 8o

17.12.2008 - 12:35 Uhr

Hallo,
ich erstelle über ein Outlook-Addin eine Mail und stelle sie in den Postausgang. Der User soll letztendlich selber die Entscheidung treffen, ob sie wirklich gesendet werden soll. Das klappt alles soweit, nur funktioniert das manuelle Versenden nicht, weil die Mail als geöffnet markiert ist. Wie löse ich das Problem?

private void SetMailToOutBox()
      {
         Application outlookApplication = new ApplicationClass();
         Outlook.NameSpace nameSpace = outlookApplication.GetNamespace("MAPI");
         nameSpace.Logon(missing, missing, true, true);
         Outlook.MAPIFolder outbox = nameSpace.GetDefaultFolder(OlDefaultFolders.olFolderOutbox);
         ComplaintMail.UnRead = true;
         int numberOfItems = outbox.Items.Count;
         ComplaintMail.Move(outbox);
         Success = numberOfItems < outbox.Items.Count;
         nameSpace.Logoff();
         Dispose();
      }
09.08.2008 - 18:19 Uhr

Hmm das hab ich jetzt nicht verstanden. Ich hab nie C&C gespielt.
Naja wie auch immer, dafür ist meine Version doppeldeutig. 😁

09.08.2008 - 16:45 Uhr

Ja warum baut man dann nicht gleich ein NOT-Kraftwerk?

02.08.2008 - 18:01 Uhr

However, ich kann immer noch nicht erkennen wo an der puren Erwähnung von Basic der Lacher vergraben ist. 🤔
Fakt ist aber daß die Rechner seinerzeit tatsächlich nicht mehr Speicher hatten.

02.08.2008 - 14:36 Uhr

Wo ist dabei der Witz? Ich hatte vor Jahrzehnten mit Basic das Programmieren gelernt und in der Firma, in der ich damals tätig war, sogar eine Software für die Auswertung der statistischen Prozesskontrolle der Produktion geschrieben - ebenfalls in Basic. Das Teil lief zur vollkommenen Zufriedenheit aller Mitarbeiter. Es gab mal eine Zeit vor Betriebssystemen mit grafischer Benutzeroberfläche. Da war der Einsatz von Basic gar nicht mal so unüblich.
Das war noch in der Zeit als Bill Gates behauptete, "640k should be enough for everybody!". Na schreib heute mal mit einer modernen Programmiersprache eine Anwendung die sich mit 640kb RAM zufrieden gibt. 😁

22.07.2008 - 12:59 Uhr

LOL den muß ich mir merken! 😁

08.07.2008 - 23:24 Uhr

Vielleicht darf ich in diesem Zusammenhang mal auf meinen StateManager verweisen. Der macht nämlich genau was hier gesucht wird.
http://cyrons-blog.spaces.live.com/blog/cns!EDC7BE32144334A!404.entry

18.06.2008 - 20:58 Uhr

Danke für den Tip. Ich habe den Stack in eine Kapazitätsbegrenzung gekapselt. =)

18.06.2008 - 19:13 Uhr

Mann bist du schnell! 🙂
Danke

18.06.2008 - 19:11 Uhr

Achso noch etwas, sorry - file mir gerade erst ein: Was ist, wenn ich mich nicht um eine solche Begrenzung kümmere. Bekomme ich dann eine OutOfMemory-Exception, die ich behandeln kann? Gibts ein best practice dafür?

18.06.2008 - 19:08 Uhr

Aha, jetzt habe ich diese komische MSDN-Formulierung verstanden. Gehe ich Recht in der Annahme, daß ich eine fixe Begrenzung nur mit einem Abfrage-Kontrukt aussenherum realisieren kann?

18.06.2008 - 18:55 Uhr

Hallo,
ich möchte die Größe eines Stacks begrenzen.
Nun steht bei MSDN über den Konstruktor von Stack<T>

Initialisiert eine neue, leere Instanz der Stack-Klasse, die über die angegebene anfängliche Kapazität, mindestens aber über die anfängliche Standardkapazität verfügt.

Was bedeutet denn "Standardkapazität? Wie groß ist sie und kann ich diesen Standardwert ändern?
Instantiiere ich diese Klasse z.B. mit einer Größe von 100, kann ich aber trotzdem viel mehr Objekte dort ablegen. Auch TrimExcess() ändert daran nichts, obwohl in der Hilfe folgendes steht:

Legt die Kapazität auf die Anzahl der tatsächlich im Stack befindlichen Elemente fest, sofern diese Anzahl unter 90 Prozent der aktuellen Kapazität liegt.

Das folgende kleine Beispiel liefert 297 Elemente zurück!

static void Main()
      {
         Stack<string> state = new Stack<string>(100);
         int amount = 1000;
         for (int i = 0; i < amount; i++)
         {
            state.Push(i.ToString());            
         }

         state.TrimExcess();

         for (int i = 0; i < state.Count; i++)
         {
            Console.WriteLine(state.Pop());
         }

         // Verhindert das selbsttätige Schließen des Konsolenfensters.
         Console.WriteLine("\nPress any key to terminate the program.");
         Console.ReadKey();
      }

Wenn ich mir vorstelle, anstatt strings packe ich große Bitmaps auf den Stack, dann wird's eng mit dem Speicher!

16.06.2008 - 14:41 Uhr

Danke, ich glaube ich werde mich für das Buch von GalileoComputung entscheiden. Es ist auf dem Stand von .net 3.5 und VS2008. =)

14.06.2008 - 11:29 Uhr

wenn es unterschiedliche Bewertungen gibt, dann liegt vielleicht daran, dass das Buch bei unterschiedlichen Lesern unterschiedlich ankommt.

Wenn ich wenigstens unterschiedliche Bewertungen gefunden hätte, aber ich habe glatt gar nichts gefunden! Mit "unparteiisch" wollte ich Herstellerbeschreibungen ausklammern. Tut mir leid wenn das falsch rübergekommen ist.

Ansonsten @all: Danke für die Tips. 🙂

14.06.2008 - 01:46 Uhr

Hallo,
ich bin zur Zeit auf der Suche nach einem guten Buch für den Einstieg in WPF. Dabei ist mir das Buch "Windows presentation foundation crashkurs" von Microsoft Press (Author Bernd Marquardt) aufgefallen. Kennt jemand das Buch? Ich hab schon im Internet nach unparteiischen Bewertungen gesucht, aber nichts gefunden.

14.05.2008 - 17:58 Uhr

Vielen Dank euch allen. Ich bin wirklich froh daß es dieses Forum gibt. 🙂
Microsoft widmet sich diesem Problem wohl noch:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1473971&SiteID=1

14.05.2008 - 15:09 Uhr

Nee sorry, ich hab mich vielleicht blöd ausgedrückt. Der Grund warum ich überhaupt IComparable benutze, ist weil ich eine Gemeinsamkeit gesucht habe, die alle Typen haben mit denen man rechnen kann. Das Constraint where T : IComparable existiert nur aus diesem Grund. So kann ich Limit<T> mit int, double, long, Single usw benutzen. Die Grundidee zu Limit<> kam mir, als ich meinen Process Sentinel bastelte. Das ist ein Programm das andere laufende Programme überwacht und feststellt, ob sie noch mit einer Langzeitoperation beschäftigt sind. Falls nicht, wird Alarm gegeben. Beim Auslesen der Prozessorlast mußte ich zu meiner Überraschung feststellen daß die Last 100 übersteigen kann (ist wichtig weil ich sie grafisch über einen Progressbar darstelle) - der Limiter war geboren. Da ich für zukünftige Projekte etwas möglichst flexibles haben will, wurde das Ding so erweitert wie es sich jetzt präsentiert.
Wenn du mir jetzt also z.B. sagen würdest, "Mensch warum nimmst du nicht Ixyz statt IComparable, weil du Ixyz ganz einfach zu jedem x-beliebigen Zahlentypen casten kannst", dann wäre das - ja wie sag ich's denn... supertoll. 😁

14.05.2008 - 13:55 Uhr

@herbivore: Hmm... das müßte ich dann aber für jeden Typen machen der irgendwie in Frage kommt. 🤔

@Peter Bucher: Danke für den Link. Der Artikel kommt gleich in mein OneNote-Notizbuch. Den Rückgabetyp wollte ich allerdings bei MethodBase belassen, weil ich denke, das bietet mehr Möglichkeiten für die Weiterverarbeitung.

14.05.2008 - 13:00 Uhr

So, fertig - hoffe ich.
Einen Wermutstropfen habe ich aber: Die Konvention (this Typ Name ... muß bei einer Extension Method strikt eingehalten werden, sonst meckert der Compiler! Darum konnte ich den Sender-Parameter nicht an die erste Stelle setzen.
Vielleicht hast du zum Schluß noch einen Tip für mich. Du siehst in dem Beispiel daß ich in der Eventhandler-Methode (LimiterProbe) Value und Maximum zu double caste, um damit zu rechnen. Es kann ja aber vorkommen daß an dieser Stelle der Typ der in IComparable geboxt ist, gar nicht bekannt ist. Was kann man da machen?

using System;
using System.Diagnostics;

namespace ExtendingLimitsV2
{
   #region Concrete Classes
   /// <summary>
   /// Stellt verschiedene Extension-Methoden zur Verfügung.    
   /// </summary>
   public static class Extensions
   {
      /// <summary>
      /// Stellt einen Eventhandler dar, der das LimitExceeded-Event verarbeitet.
      /// </summary>      
      public delegate void OverloadEventHandler(object sender, OverloadEventArgs e);

      /// <summary>
      /// Tritt ein, wenn ein an die Limit-Methode übergebener Wert
      /// die durch "maximum" angegebene Obergrenze überschreitet.
      /// </summary>
      public static event OverloadEventHandler LimitExceeded;

      /// <summary>
      /// Verhindert daß eine Zahl einen Maximalwert überschreitet.
      /// </summary>
      /// <typeparam name="T">IComparable</typeparam>
      /// <param name="value">Wert eines Typs
      /// der das IComparable-Interface implementiert.</param>
      /// <param name="maximum">Der Maximalwert, den eine Zahl annehmen darf.</param>
      /// <returns>Der gefilterte Wert.</returns>
      /// <example>decimal result = testValue.Limit(100);</example>
      public static T Limit<T>(this T value, T maximum)
         where T : IComparable<T>
      {
         return value.CompareTo(maximum) < 1 ? value : maximum;
      }

      /// <summary>
      /// Verhindert daß eine Zahl einen Maximalwert überschreitet.
      /// </summary>
      /// <typeparam name="T">IComparable</typeparam>
      /// <param name="value">Wert eines Typs
      /// der das IComparable-Interface implementiert.</param>
      /// <param name="maximum">Der Maximalwert, den eine Zahl annehmen darf.</param>
      /// <param name="invoker">Die Klasse, die Limit aufgerufen hat.</param>
      /// <returns>Der gefilterte Wert.</returns>
      ///<example>decimal result = testValue.Limit(100, this);</example>
      public static T Limit<T>(this T value, T maximum, object invoker)
         where T : IComparable<T>
      {
         if(value.CompareTo(maximum) < 1)
            return value;
         else
         {
            if(LimitExceeded != null)
            {
               OverloadEventArgs e =
                  new OverloadEventArgs((IComparable)value, (IComparable)maximum);
               LimitExceeded(invoker, e);
            }
            return maximum;
         }
      }

      // Weitere Extension-Methods...
   }

   //==========================================================================


   /// <summary>
   /// Stellt Daten für das LimitExceeded-Event zur Verfügung.
   /// </summary>
   public class OverloadEventArgs : EventArgs
   {
      /// <summary>
      /// Initialisiert eine neue Instanz der <see cref="OverloadEventArgs"/> Klasse.
      /// </summary>      
      public OverloadEventArgs(IComparable value, IComparable maximum)
      {
         StackTrace st = new StackTrace(true);
         /* Index 0: ctor von OverloadEventArgs
          * Index 1: Eventauslöser (ist Limit<T>)
          * Index 2: Die Methode die Limit<T> verwendet. */
         StackFrame sf = st.GetFrame(2);
         this.InvokerMethod = sf.GetMethod();         
         this.Maximum = maximum;
         this.Value = value;
      }

      /// <summary>
      /// Gibt die Methode zurück,
      /// durch die das LimitExceeded-Event ausgelöst wurde.
      /// </summary>      
      public System.Reflection.MethodBase InvokerMethod { get; private set; }

      /// <summary>
      /// Ruft das an die Limit-Methode übergebene Maximum ab.
      /// </summary>
      public IComparable Maximum { get; private set; }

      /// <summary>
      /// Ruft den an die Limit-Methode übergebenen Wert ab.
      /// </summary>     
      public IComparable Value { get; private set; }
   }
   #endregion
   #region Demo
   //==========================================================================

   class ClassA
   {
      static void Main()
      {
         ClassB anotherLimitBreaker = new ClassB();
         ClassC observer = new ClassC();
         observer.AttachToLimitExceededEvent();
         int testValue = 150;
         // Die Version ohne sender und damit ohne Event:
         int limitedResult = testValue.Limit(100);
         // limitedResult wird 100 sein.
         Console.WriteLine("limitedResult ist {0}\r\n", limitedResult.ToString());
         anotherLimitBreaker.ExceedLimit();

         // Verhindert das selbsttätige Schließen des Konsolenfensters.
         Console.WriteLine("\nPress any key to terminate the program.");
         Console.ReadKey();
      }
   }

   //==========================================================================

   // Ein weiterer Limit-Brecher
   class ClassB
   {
      public void ExceedLimit()
      {
         double testValue = 3.141592654;
         // Die Version mit invoker und dadurch mit Event:
         double limitedResult = testValue.Limit(2.0, this);
      }
   }

   //==========================================================================

   // Observer
   class ClassC
   {
      public void AttachToLimitExceededEvent()
      {
         Extensions.LimitExceeded +=
            new Extensions.OverloadEventHandler(LimiterProbe);
      }

      protected void LimiterProbe(object sender, OverloadEventArgs e)
      {
         Console.WriteLine(
            "In {0}.{1} wurde das erlaubte Maximum von {2} durch {3} überschritten!",
            sender.ToString(), e.InvokerMethod.ToString(),
           e.Maximum.ToString(), e.Value.ToString());

         // Wenn man value und maximum castet, kann man damit auch rechnen:         
         Console.WriteLine("Der Wert überstieg das Maximum um {0}%",
            Math.Round(((double)e.Maximum / (double)e.Value * 100), 1));

         // Erst wenn das Abo nicht mehr gebraucht wird:
         DetachStaticEvents();
      }

      /// <summary>
      /// Löst Verbindungen für statische Events auf, um Speicherlecks zu verhindern.
      /// </summary>
      public void DetachStaticEvents()
      {
         /* Laut MSDN ergeben sich Speicherlecks,
          * wenn man Verbindungen zu statischen Events nicht wieder auflöst
          * (siehe ThreadException Event im MSDN). */
         Extensions.LimitExceeded -=
            new Extensions.OverloadEventHandler(LimiterProbe);
      }
   }
   #endregion
}
14.05.2008 - 10:40 Uhr

Wow, vielen Dank für deine Mühe, herbivore. Ich werde das alles durchtesten und mich dann später wieder melden.

13.05.2008 - 21:40 Uhr

Ich krieg's nicht gebacken.
Nochmal:

public static T Limit<T>(this T value,...

value hat Pi als Inhalt und T ist vom Typ double. Sonst gibt es da keine weiteren Inhalte. Ich hab's mir gerade per Quickwatch angeschaut. 🤔
Korrigier mich falls ich mich irre, aber das this in einer Extension Method bezieht sich auf die zu erweiternde Klasse (hier: Double) und nicht auf den Aufrufer.

13.05.2008 - 21:04 Uhr

Hups, ich hab mich zu früh gefreut. Du schreibst

Für sender sollte beim Feuern des Events immer this übergeben werden.

Das Event wird aber in einer statischen Klasse gefeuert. Da gibt's this nicht, und die Klasse muß statisch sein, weil nur in einer solchen eine Extension Method definiert werden darf. Ausserdem bekäme ich dann beim Auswerten nur die Extension-Klasse angegeben und nicht die Klasse in der das Limit überschritten wurde.

13.05.2008 - 20:19 Uhr

Herzlichen Dank herbivore. 🙂
So werde ich es machen.

13.05.2008 - 20:02 Uhr

Ist das so OK?

using System;
using System.Diagnostics;

namespace ExtendingLimits
{
   /// <summary>
   /// Stellt verschiedene Extension-Methoden zur Verfügung.    
   /// </summary>
   public static class Extensions
   {
      /// <summary>
      /// Stellt einen Eventhandler dar, der das LimitExceeded-Event verarbeitet.
      /// </summary>      
      public delegate void Overload(IComparable value, IComparable maximum,
         OverloadEventArgs e);

      /// <summary>
      /// Tritt ein, wenn ein an die Limit-Methode übergebener Wert
      /// die durch "maximum" angegebene Obergrenze überschreitet.
      /// </summary>
      public static event Overload LimitExceeded;

      /// <summary>
      /// Verhindert daß eine Zahl einen Maximalwert überschreitet.
      /// </summary>
      /// <typeparam name="T">IComparable</typeparam>
      /// <param name="value">Wert eines Typs
      /// der das IComparable-Interface implementiert.</param>
      /// <param name="maximum">Der Maximalwert, den eine Zahl annehmen darf.</param>
      /// <returns>Der gefilterte Wert.</returns>
      /// <example>decimal result = testValue.Limit(100);</example>
      public static T Limit<T>(this T value, T maximum) where T : IComparable<T>
      {
         return value.CompareTo(maximum) < 1 ? value : maximum;
      }

      /// <summary>
      /// Verhindert daß eine Zahl einen Maximalwert überschreitet.
      /// </summary>
      /// <typeparam name="T">IComparable</typeparam>
      /// <param name="value">Wert eines Typs
      /// der das IComparable-Interface implementiert.</param>
      /// <param name="maximum">Der Maximalwert, den eine Zahl annehmen darf.</param>
      /// <param name="sender">Die Klasse, die Limit aufgerufen hat.</param>
      /// <returns>Der gefilterte Wert.</returns>
      ///<example>decimal result = testValue.Limit(100, this);</example>
      public static T Limit<T>(this T value, T maximum, object sender)
         where T : IComparable<T>
      {
         OverloadEventArgs e = new OverloadEventArgs(sender);
         if(value.CompareTo(maximum) < 1)
            return value;
         else
         {
            if(LimitExceeded != null)
               LimitExceeded((IComparable)value, (IComparable)maximum, e);
            return maximum;
         }
      }

      // Weitere Extension-Methods...
   }

   //==========================================================================


   /// <summary>
   /// Stellt Daten für das LimitExceeded-Event zur Verfügung.
   /// </summary>
   public class OverloadEventArgs : EventArgs
   {
      /// <summary>
      /// Initialisiert eine neue Instanz der <see cref="OverloadEventArgs"/> Klasse.
      /// </summary>      
      public OverloadEventArgs(object sender)
      {
         this.Caller = sender;
         StackTrace st = new StackTrace(true);
         /* Index 0: ctor von OverloadEventArgs
          * Index 1: Eventauslöser (ist Limit<T>)
          * Index 2: Die Methode die Limit<T> verwendet. */
         StackFrame sf = st.GetFrame(2);
         CallerMethod = sf.GetMethod();
      }

      /// <summary>
      /// Gibt den Namespace und die Klasse zurück,
      /// durch die das LimitExceeded-Event ausgelöst wurde.
      /// </summary>
      public object Caller { get; private set; }

      /// <summary>
      /// Gibt die Methode zurück,
      /// durch die das LimitExceeded-Event ausgelöst wurde.
      /// </summary>      
      public System.Reflection.MethodBase CallerMethod { get; private set; }
   }

   //==========================================================================

   class ClassA
   {
      static void Main()
      {
         ClassB anotherLimitBreaker = new ClassB();
         ClassC observer = new ClassC();
         observer.AttachToLimitExceededEvent();
         int testValue = 150;
         // Die Version ohne sender und damit ohne Event:
         int limitedResult = testValue.Limit(100);
         // limitedResult wird 100 sein.
         Console.WriteLine("limitedResult ist {0}\r\n", limitedResult.ToString());
         anotherLimitBreaker.ExceedLimit();

         // Verhindert das selbsttätige Schließen des Konsolenfensters.
         Console.WriteLine("\nPress any key to terminate the program.");
         Console.ReadKey();
      }
   }

   //==========================================================================

   // Ein weiterer Limit-Brecher
   class ClassB
   {
      public void ExceedLimit()
      {
         double testValue = 3.141592654;
         // Die Version mit sender und dadurch mit Event:
         double limitedResult = testValue.Limit(2.0, this);
      }
   }

   //==========================================================================

   // Observer
   class ClassC
   {
      public void AttachToLimitExceededEvent()
      {
         Extensions.LimitExceeded +=
            new Extensions.Overload(LimiterProbe);
      }

      void LimiterProbe(IComparable value, IComparable maximum, OverloadEventArgs e)
      {
         Console.WriteLine(
            "In {0}.{1} wurde das erlaubte Maximum von {2} durch {3} überschritten!",
            e.Caller.ToString(), e.CallerMethod.ToString(),
            maximum.ToString(), value.ToString());

         // Wenn man value und maximum castet, kann man damit auch rechnen:         
         Console.WriteLine("Der Wert überstieg das Maximum um {0}",
            ((double)value - (double)maximum));

         // Erst wenn das Abo nicht mehr gebraucht wird:
         DetachStaticEvents();
      }

      /// <summary>
      /// Löst Verbindungen für statische Events auf, um Speicherlecks zu verhindern.
      /// </summary>
      private void DetachStaticEvents()
      {
         /* Laut MSDN ergeben sich Speicherlecks,
          * wenn man Verbindungen zu statischen Events nicht wieder auflöst
          * (siehe ThreadException Event im MSDN). */
         Extensions.LimitExceeded -=
            new Extensions.Overload(LimiterProbe);
      }
   }
}

Das hier gibt die Demo aus:
limitedResult ist 100

In ExtendingLimits.ClassB.Void ExceedLimit() wurde das erlaubte Maximum von 2 durch 3,141592654 überschritten!
Der Wert überstieg das Maximum um 1,141592654

Press any key to terminate the program.

13.05.2008 - 13:52 Uhr

Also es geht um folgendes:
Ich habe eine eine Extension Method Limit<T> für IComparable<T> geschrieben, die einen Wert auf ein Maximimum (das als Parameter übergeben wird) beschneidet. Wird ein Wert beschnitten, feuert die Methode ein Event LimitExceeded, das von jeder beliebigen Klasse abonniert werden kann. Da innerhalb einer Klasse Limit<> in verschiedenen Methoden aufgerufen werden kann, möchte ich einen Observer gerne wissen lassen, in welcher der Methoden diese Grenzwertüberschreitung denn stattgefunden hat (zwecks besserer Auswertungs- und Reaktionsmöglichkeiten).

EDIT: Das Event benutzt einen custom Delegate:

public delegate void Overload(IComparable value, IComparable maximum, object sender);

13.05.2008 - 13:37 Uhr

Moin,
liest man object sender eines Eventhandlers aus, bekommt man ja bekanntlich
Namespace.KlassenName
Das reicht mir aber nicht. Ich hätte gerne
Namespace.KlassenName.MethodenName
Hat jemand einen Tip?
Wer wissen möchte, um was es mir konkret geht, kann sich mal diesen Blogeintrag anschauen:
Extending the Extension

29.04.2008 - 15:29 Uhr

Ja klar! Danke für den Schubs. 🙂
Warum bin ich darauf nicht selber gekommen? mit der Hand vor die Stirn hau

29.04.2008 - 15:25 Uhr

Hab ich schon ausprobiert. Das Form wird nur zum Teil gerendert. Die Listbox steckt in einem Group-Panel, und das wird nicht gerendert solange das Listbox-Update nicht fertig ist.

29.04.2008 - 15:20 Uhr

Hallo,
ich habe mir gerade eine kleine Prozessüberwachung gechrieben. Dazu wird direkt nach Programmstart eine Liste aller laufenden Prozesse in eine ListBox übergeben. Das dauert ein paar Sekunden. Zur Zeit läuft das über das Load-Event der Form. Nachteil: Das Form wird erst gerendert wenn die ListBox befüllt ist.
Wie kann ich die ListBox automatisch befüllen NACHDEM das Form gerendert ist?

22.04.2008 - 00:31 Uhr

Also ich kann mich darin nicht erkennen, denn meine Frau verhindert immer wieder erfolgreich, daß ich zu tief in das Universum von Bits und Bytes eintauche. 😁 😉
Aber mal im Ernst, ich muß gestehen daß mein Hirn viel zu oft "programmiert", obwohl ich gar nicht am Computer sitze, und so passiert es hin und wieder daß ein Gesprächspartner einen Satz wiederholen muß, weil ich mal wieder geistig in ganz anderen Sphären schwebe.

19.04.2008 - 20:04 Uhr

Das ist ein einfaches System? Ich möchte gar nicht wissen wie dann etwas kompliziertes aussieht. X(

19.04.2008 - 11:02 Uhr

Also ist es im Prinzip egal wie ich es schreibe. Danke 🙂

19.04.2008 - 00:43 Uhr

Moin,
wo ist eigentlich der Unterschied zwischen

Console.Out.WriteLine

und

Console.WriteLine

? Ich meine, gibt es einen Grund, warum man das Eine dem Anderen vorziehen sollte?

18.04.2008 - 23:49 Uhr

Hast du mal eine Binärdatei mit einem Texteditor geöffnet? Was man da liest, ergibt keinen Sinn (jedenfalls nicht für das menschliche Auge) - wie denn auch? 🙂
Hast du in der Hilfe mal das Stichwort SerialPort eingegeben? Da gibt's ein schönes Beispiel. Ausserdem hab ich gerade mal unter SerialPort.ReadExisting nachgeschaut. Das steht unter anderem
"Wenn es erforderlich ist, zwischen dem Lesen von Text und dem Lesen von Binärdaten aus dem Stream zu wechseln, wählen Sie ein Protokoll aus, dass die Grenze zwischen Text und Binärdaten genau definiert, beispielsweise durch manuelles Lesen von Bytes und Entschlüsseln von Daten."

Hast du das beachtet?
Das meinte ich mit der Filterfunktion. Wenn Literale und binäre Daten ankommen, mußt du dafür sorgen daß nur Literale zur Ausgabe (Textbox) gelangen, denn Binärdaten in einer Textbox machen keinen Sinn. Natürlich bringt die ToString-Methode da auch nichts.

Etwas anderes ist es natürlich, wenn du z.B. für das Debugging einer seriellen Kommunikation ein Monitoring aller ankommenden Daten brauchst. In dem Fall könnte ich mir vorstellen, daß du den Stream in ein Byte-Array schreibst. Das kannst du dann über ToString() in eine lesbare Ausgabe wandeln (Zahlen von 0 bis 255). Über

Convert.ToString(byteVariable, 16);

lässt sich das dann leicht in Hex-Werte wandeln.

18.04.2008 - 23:15 Uhr

Diese Rechtecke sind Daten ausserhalb der darstellbaren Zeichen (keine Literale). Schau mal in der :rtfm: unter String.Normalize nach. Das könnte dir evtl. helfen. Noch besser wäre es vielleicht, wenn du in deiner Applikation eine Filterfunktion für Literale vorschaltest.

07.04.2008 - 13:26 Uhr

Es ist also oft so, dass sich aktiv und passiv beim Übergang von der realen Welt in den Rechner vertauscht.

Danke für deinen Kommentar, herbivore.
Ja das war wohl einer der Gründe, warum ich programmiertechnisch auf dem Holzweg war.
*Als ich gestern die Links gefunden hatte, war ich sofort total fasziniert von dem Thema. Ich habe es nur kurz überflogen, aber ich denke
active objects und Futures sind genau was ich mir vorstelle. Es gibt jetzt 'ne Menge für mich zu studieren. 😁

EDIT:
*: Was mich an meinem exemplarischen Konstrukt etwas stört, ist die Tatsache, daß neben den eigentlichen Akteuren (Vater, Sohn, Kiosk) und den passiven Objekten (Geld, Bier) noch ein Kontrollobjekt existiert, daß alle Aktionen steuert. Ich will damit nicht sagen daß ich auf Kontrollobjekte verzichten will. Das geht wohl auch gar nicht, aber ich wünsche mir eine bessere Verteilung der Aktivitäten, um OOP näher an die reale Welt zu bringen. Wie ich sehe, arbeitet Microsoft an der gleichen Idee.

07.04.2008 - 01:56 Uhr

Hallo,
nach dem berechtigten Rüffel von herbivore über meinen prozeduralen Programmierstil, versuche ich mich in die Materie OOP zu vertiefen. In diesem Zusammenhang habe ich ein kleines Progrämmchen geschrieben, was Objekte bzw. Zustände von einer Klasse zur anderen durchreicht. Dabei kommt mir etwas seltsam vor: In der realen Welt sind viele Objekte aktiv, bei der OOP sind die Objekte meistens passiv (jedenfalls bei allen Codes die mir bis jetzt begegnet sind). Ich möchte das hier mal verdeutlichen. In meinem "Programm" wird der gesamte Ablauf von der Klasse Program gesteuert:

class Program
   {
      static void Main()
      {
         int anzahl = 1;
         decimal geldBetrag = 1.0m;
         Sohn.NimmGeld(Vater.GibGeld(geldBetrag));
         Kiosk.NimmGeld(Sohn.GibGeld(geldBetrag));
         Sohn.NimmBier(Kiosk.GibBier(anzahl));
         Vater.NimmBier(Sohn.GibBier(anzahl));
      }
   }

   /* Output:
      Vater gibt 1,0 Geld an Sohn.
      Sohn nimmt 1,0 Geld von Vater.
      Sohn gibt 1,0 Geld an Kiosk.
      Kiosk nimmt 1,0 Geld von Sohn entgegen.
      Kiosk gibt 1 Bier an Sohn.
      Sohn nimmt 1 Bier von Kiosk entgegen.
      Sohn übergibt 1 Bier an Vater.
      Vater nimmt 1 Bier von Sohn entgegen.
      Vater macht die Flasche auf.
      Prost
   */

   public class Bier
   {
      public Bier() { }
      public Bier(int anzahl)
      {
         this.Anzahl = anzahl;
      }
      public int Anzahl { get; set; }
      public int Fuellstand { get; set; }
      public bool Offen { get; set; }
   }

   public class Geld
   {
      public decimal Betrag { get; set; }

      public Geld() { }
      public Geld(decimal betrag)
      {
         this.Betrag = betrag;
      }
   }

   class Vater
   {
      private static Geld meinGeld = new Geld(100);
      private static Bier meinBier;

      public static Geld GibGeld(decimal betrag)
      {
         if(betrag < meinGeld.Betrag)
         {
            meinGeld.Betrag -= betrag;
            Console.WriteLine("Vater gibt {0} Geld an Sohn.", betrag);
            return new Geld(betrag);
         }
         else
            throw new ArithmeticException("Ich hab kein Geld.");
      }

      public static void NimmBier(Bier flasche)
      {
         meinBier = flasche;
         Console.WriteLine("Vater nimmt {0} Bier von Sohn entgegen.", meinBier.Anzahl);
         meinBier.Fuellstand = 100; // in Prozent
         MachAuf();
      }

      private static void MachAuf()
      {
         if(meinBier.Anzahl > 0)
         {
            Console.WriteLine("Vater macht die Flasche auf.");
            meinBier.Offen = true;
            Trinken();
         }
         else
            Console.WriteLine("Wo ist mein Bier?!");
      }

      private static void Trinken()
      {
         Console.WriteLine("Prost");
         meinBier.Fuellstand = 0;
      }
   }

   public class Sohn
   {
      private static Geld meinGeld = new Geld();
      public static Bier meinBier;
      private Kiosk laden;
      public Sohn()
      {
         laden = new Kiosk();
      }

      public static void NimmGeld(Geld betrag)
      {
         meinGeld.Betrag = betrag.Betrag;
         Console.WriteLine("Sohn nimmt {0} Geld von Vater.", meinGeld.Betrag);
      }

      public static Geld GibGeld(decimal betrag)
      {
         if(betrag <= meinGeld.Betrag)
         {
            Console.WriteLine("Sohn gibt {0} Geld an Kiosk.", meinGeld.Betrag);
            return meinGeld;
         }
         else
            throw new ArithmeticException("Ich hab kein Geld.");
      }

      public static void NimmBier(Bier flasche)
      {
         meinBier = flasche;
         Console.WriteLine("Sohn nimmt {0} Bier von Kiosk entgegen.", meinBier.Anzahl);
      }

      public static Bier GibBier(int anzahl)
      {
         if(meinBier.Anzahl >= anzahl)
         {
            Console.WriteLine("Sohn übergibt {0} Bier an Vater.", meinBier.Anzahl);
            return meinBier;
         }
         else
            throw new ArithmeticException("Ich hab kein Bier.");
      }
   }

   class Kiosk
   {
      private static Bier meinBier = new Bier(1000);
      private static Geld meinGeld = new Geld();

      public static Bier GibBier(int anzahl)
      {
         meinBier.Anzahl -= anzahl;
         Console.WriteLine("Kiosk gibt {0} Bier an Sohn.", anzahl);
         return new Bier(anzahl);
      }

      public static void NimmGeld(Geld betrag)
      {
         meinGeld.Betrag += betrag.Betrag;
         Console.WriteLine("Kiosk nimmt {0} Geld von Sohn entgegen.", meinGeld.Betrag);
      }
   }

Alle Klassen, mit Ausnahme von Program sind passive Objekte. Nun interessiert mich, ob es in der Welt der OOP so etwas wie "Active Objects" gibt, also Klassen die in eigenen Threads laufen und aktiv mit anderen Objekten agieren. Gibt es so etwas? Wäre so etwas sinnvoll?
Zu diesem Thema habe ich ein paar interessante Artikel gefunden:
Active objects tutorial mit C omega

jaredpar's Blog über Active objects und Futures

20.03.2008 - 17:17 Uhr

Hallo,
normalerweise wird ein Extensionfilter ja so gesetzt:


OpenFileDialog open = new OpenFileDialog();
open.Filter = "BMP Bild|*.bmp|GIF Bild|*.gif|JPG Bild|*.jpg|PNG Bild|*.png|TIFF Bild|*.tif";

Ein Nachteil dabei ist, daß ich in der Dialogbox dann einen der angebotenen Bildtypen auswählen muß. Ich möchte daß im Filter-Dropdown multiple Extensions in einer Zeile stehen (z.B. Bilder (.bmp;.jpg;*.png)) und ich so alle Bilder zur Auswahl aufgelistet bekomme, die einen der angegebenen Extensions aufweisen. Daß so etwas machbar ist, machen andere Anwendungen ja vor. Nun wüßte ich gerne wie das gemacht wird.

17.03.2008 - 14:04 Uhr

Danke, jetzt ist der Groschen gefallen. =)

16.03.2008 - 20:30 Uhr

Genau das wollte ich zum Ausdruck bringen. Mit einer statischen Klasse ist so ein Blödsinn gar nicht erst möglich. 🙂
Achso, noch etwas. Bitte versteh mich nicht falsch, herbivore. Ich zweifle in keinster Weise deine Worte an, nur verstehe ich deinen ersten Post nicht so ganz. Du schreibst, ein Singleton ist flexibler und objektorientierter, - aber warum ist das so?