0

I need a little help i am using a class and want to set the properties based on choice on type int,string and datetime here is my code that i wrote but as my constructor will be confused between public string paramValue and public int? paramValue what is the best way to set properties based on choice so only one property can be set a time.Thanks for any suggestion

public class PassData
{
    private string _ParamName { get; set; }
    private int? _ParamValueInt { get; set; }
    private string _ParamValueString { get; set; }
    private DateTime? _ParamValueDateTime { get; set; }


    public string paramName
    {
        get { return _ParamName; }
        set { _ParamName = value;}
    }

    public string paramValue
    {
        get { return _ParamValueString; }
        set {_ParamValueString = value; }
    }

    public int? paramValue
    {
        get { return _ParamValueInt; }
        set { _ParamValueInt = value; }
    }

    public PassData(string ParamName, int ParamValue)
    {
        paramName = ParamName;
        paramValue = ParamValue;
    }
    public PassData(string ParamName, string ParamValue)
    {
        ParamName = ParamName;
        ParamValueString = ParamValue;
    }
    public PassData(string ParamName, DateTime ParamValue)
    {
        ParamName = ParamName;
        ParamValueDateTime = ParamValue;
    }
}
leppie
  • 115,091
  • 17
  • 196
  • 297
Pamma
  • 1,455
  • 9
  • 16
  • 3
    Your code does not compile. You can't have 2 properties with the same name. And if you could, you shouldn't. Thinking up good names is hard but it is half the work. It would prevent this from being a problem. – H H Jul 24 '13 at 17:01
  • 1
    you cannot declare the same property name twice with two different return types. – nicholas Jul 24 '13 at 17:01
  • 1
    You are a bit confused on the usage of properties and parameters. – chaliasos Jul 24 '13 at 17:02
  • Why not simply `public class PassData { public TDataType Value {get;set;} }` – asawyer Jul 24 '13 at 17:03
  • 1
    your private members should typically be parameters, not properties. also, not critical, but your capitalization convention is backwards. public properties are typically Pascal capitalized (`public string ParamValue`), while private parameters are typically Camel capitalized (`private string _paramValue`) - with or without the underscore – nicholas Jul 24 '13 at 17:07
  • It's unclear to me what problem you are trying to solve, so it's hard to give specific advice. As you see in other responses, generics may be an answer, using a greatest common denominator like `object` may also apply. – neontapir Jul 24 '13 at 17:14

2 Answers2

1

Basically, you can't have multiple properties on an object that only differ by type. You have a few options.

1) Create a single property that can hold various types:

private Object _paramValue;
public Object ParamValue
{
   get { return _paramValue; }
   set {_paramValue= value; }
}

In your setter, you can throw an exception if the value is a type you don't like. You'd also have to upcast the result every time you called the getter, making this solution not ideal. If you want to go this route, I'd suggest making the property an interface, and defining various implementations for the types of data you need.

2) Create a generic class:

public class PassData<T>
{
   private T _paramValue;
   public T paramValue
   {
      get { return _paramValue; }
      set {_paramValue= value; }
   }
}

This has the disadvantage of not being able to change the type after the instance is created. It was unclear if this was a requirement for you.

I like this design as it provides for the possibility of making the constructor for this class private:

public class PassData<T>
{
   private PassData(T value)
   {
      this._paramValue = value;
   }
}

If you did this, you can create overloaded static methods to allow the creation of instances:

public static PassData<String> CreateValue(string value)
{
   return new PassData<String>(value);
}

public static PassData<Int32> CreateValue(Int32 value)
{
   return new PassData<Int32>(value);
}

That way, you can control what types can be created.

Mike Christensen
  • 88,082
  • 50
  • 208
  • 326
1

Not an answer (in the sense that it does not offer you a way to do what you're trying to do, as Mike Christensen's answer covers it). I just wanted to get more into why what you are trying to do is not working. Your expectation for it to work is not unreasonable per se, the issue is that c# is not polymorphic on return values. I think some other languages are, C# is not.

i.e. while in c#, you can do:

public void test(int val) {}
public void test(string val) {}
// When you call `test` with either an int or a string, 
// the compiler will know which one to call

you CAN'T do:

public int test() {return 1;}
public string test() {return "1";}
// does not compile. The compiler should look at the call
// site and see what you assign the result of "test()" to
// to decide. But there are various edge cases and it was decided
// to leave this out of the language

Now, the get on string paramValue is functionally equivalent to this scenario. You're trying to get the compiler to decide which paramValue to call based on the return value.

Paolo Falabella
  • 24,914
  • 3
  • 72
  • 86
  • +1 for a good suggestion and provide me knowledge.I might need to read C# in depth. – Pamma Jul 24 '13 at 17:25
  • @Pamma by the way, if you want to express a type that can contain either a string or a int or a DateTime, you may want to take a look at the accepted answer to this question: http://stackoverflow.com/questions/3151702/discriminated-union-in-c-sharp (also look in the comments, where Juliet offers an even more beautiful alternative, IMO) – Paolo Falabella Jul 24 '13 at 20:14