Parameterklasse mit verschiedenen Typen



  • wie wäre es, anstatt generics einfach den parameter als object zu speichern und valuetypes zu "boxen" (siehe msdn)

    man kann ints, floats, bools etc einfach als Object static-casten und zurück 😉

    also könntest du einfach eine liste auf Object typisieren und der parameter wäre entsprechend immer anders. du könntest dann sogar klassen und structs als parameter haben.

    siehe auch diesen artikel

    ist das was du meinst?



  • Dann würde ich eher den korrekten Typ speichern und beim abfragen boxen.



  • Da Problem ist aber, dass ich dann in der parameterklasse immer Typ, als meinetwegen enum, mit hinterlegen muss, damit ich später weiß, in was ich casten muss.

    Noch eine Idee:

    Wie wäre es, wenn ich die Werte als string übergebe und intern mit double.tryparse ... umwandle? Weil irgendwo muss ich sie ja sowieso mal als string visualisieren (Listview, Textbox).



  • Hast du dir schonmal überlegt wie du die Parameter verwenden willst? Hast du ein konkretes Anwendungsbeispiel?



  • Ja.

    Es gibt einen Dialog, der die Parameter untereinnanderweg in einem ListView darstellt:

    Par1 true
    Par2 0.75
    Par3 88.4
    Par4 false

    Die Werte werden im ListView über Textfelder (double, int) und ComboBoxen (bool) editiert und nach der Eingabe an den Parameter zurückgegeben.



  • Dafür kannst du z.B. ToString() verwenden. Beispiel:

    class Program
      {
        static void Main(string[] args)
        {
          List<IParam> foo = new List<IParam>();
          foo.Add( new Param<int>( "parm1", 42 ) );
          foo.Add( new Param<string>( "parm2", "is" ) );
          foo.Add( new Param<bool>( "parm3", true ) );
    
          foreach ( IParam p in foo )
          {
            Console.Write( string.Format( "{0} ", p.Value.ToString() ) );
          }
          Console.Read();
        }
      }
    
      public interface IParam
      {
        object Value { get; }
      }
    
      public class Param<T> : IParam
      {
        private T mValue;
        private string mName;
    
        public Param( string name, T value )
        {
          mName = name;
          mValue = value;
        }
    
        #region IParam Members
    
        public object Value
        {
          get { return mValue; }
        }
    
        #endregion
      }
    


  • So ähnlich hab ich es auch schon angedacht, das Problem ist dass Rückschreiben der Parameterwerte. Man muss immer den Typ wissen.



  • Das musst du ohnehin und es macht auch durchaus Sinn ihn zu wissen.



  • Cooler wäre es, man hätte eine Funktion

    par.SetParameter(Template wert);

    die automatisch gewählt würde, abhängig vom Typ. So wie bei Variant.

    Vielleich ginge es so, wenn man als Übergabetyp object nimmt und intern castet, wie bei jule37 schon beschrieben.



  • F98 schrieb:

    Cooler wäre es, man hätte eine Funktion

    par.SetParameter(Template wert);

    die automatisch gewählt würde, abhängig vom Typ. So wie bei Variant. [...]

    das sollte aber mit überladenen methoden funktionieren

    // stark verallgemeinerter pseudocode
    class ...
    {
        public void SetParameter(int wert)
        {
            ...
        }
    
        public void SetParameter(float wert)
        {
            ...
        }
    }
    

    und schon wählt der compiler automatisch die methode passend zum typen des parameters. man muss sie halt alle einmal schreiben, aber ich schätze mal das wären dann eh alles einzeiler.

    edit: nochmal über dein problem nachgedacht... genaugenommen hast du doch key - value paare (name / wert des parameters). warum nicht einfach ein dictionary benutzen?

    object ist im prinzip der variant typ von c#, da object ja auch jeder beliebige wertetyp sein kann. den typen eines objekts zur laufzeit erfährst du mit dem schlüsselwort "is"

    if(parameter.Value is int)
        ...
    


  • und schon wählt der compiler automatisch die methode passend zum typen des parameters. man muss sie halt alle einmal schreiben, aber ich schätze mal das wären dann eh alles einzeiler.

    Da er ja anscheind jeden möglichen Typ unterstützen will wäre sowas eher die Lösung der Wahl:

    // stark verallgemeinerter pseudocode
    class ...
    {
        public void SetParameter<T>(T wert)
        {
            ...
        }
    }
    

    Das Problem ist aber, dass er den Typ immer noch "boxen" muss.

    edit: nochmal über dein problem nachgedacht... genaugenommen hast du doch key - value paare (name / wert des parameters). warum nicht einfach ein dictionary benutzen?

    Das ist ja nun keine Lösung für das Problem.

    object ist im prinzip der variant typ von c#, da object ja auch jeder beliebige wertetyp sein kann. den typen eines objekts zur laufzeit erfährst du mit dem schlüsselwort "is"

    Nein, die Idee hinter Variant ist etwas anders. Außerdem ist eine so "statische" Lösung nicht unbedingt etwas, was man will...

    Hier noch ne Idee

    public abstract class ParamBase
      {
        string mName;
    
        public ParamBase( string name )
        {
          name = mName;
        }
    
        public string Name 
        {
          get { return mName; }
        }
    
        public object Value
        {
          get { return GetInternal(); }
        }
    
        public T ValueAs<T>()
        {
          return (T)GetInternal();
        }
    
        public void SetValue<T>( T value )
        {
          SetInternal( value );
        }
    
        protected abstract void SetInternal( object obj );
        protected abstract object GetInternal();
      }
    
      public class Param<T> : ParamBase
      {
        private T mValue;
    
        public Param( string name, T value ) : base( name )
        {
          mValue = value;
        }
    
        protected override void SetInternal(object obj)
        {
          mValue = ( T )obj;
        }
    
        protected override object GetInternal()
        {
          return mValue;
        }
      }
    


  • Danke Euch beiden erstmal für die Anregungen!


Anmelden zum Antworten