5

I have a property that looks like this:

private int clientID;

    public int ClientID
    {
        get { return clientID; }
        set { clientID = value; }
    }

I would like to be able to pass in a string to this property so that the setter will convert it for me. How do I do that?

I know how to do the conversion, I just need to know how to pass in a string without it throwing a type error.

Ola Ström
  • 4,136
  • 5
  • 22
  • 41
Tomas Beblar
  • 51
  • 1
  • 1
  • 5

9 Answers9

10

You can't, basically. Options:

  • Have a second property for the ClientID as text (backed by the same field)
  • Have a separate method (e.g. SetClientID(string))
  • Change the property type to object and do different things based on the value passed in (urgh - please don't do this!)
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Come on Jon, let we answer some questions too =) – Tocco Jul 19 '11 at 21:28
  • 3
    There's a fourth alternative. Change the property type to a custom type and provide implicit cast operators. It falls into the same category as *urgh - please don't do this*, but I thought I should mention it. – Lasse V. Karlsen Jul 19 '11 at 21:30
  • @Tocco I think you (and I) have to change our daily rhythm in order to beat Jon Skeet, I have contemplated trying to skew my sleep pattern by 8 hours and see if that helps bud sadly nobody wants to employ me for programming work during nightly hours here in Norway. – Lasse V. Karlsen Jul 19 '11 at 21:34
  • We have a running joke at work that Jon Skeet is actually more than one person lol circumstantially reinforced with stupidly quick and detailed answers. – Adam Houldsworth Jul 19 '11 at 21:39
  • @Tocco I hate to disagree, but Jon Skeet is not a myth. Here on SO we deal in *facts*, and the definition of myth is "an invented story" (http://dictionary.reference.com/browse/myth). If someone invented Jon Skeet, then who did I watch at NDC this year? Could it be ... *gasp* ... Tony the Pony? – Lasse V. Karlsen Jul 19 '11 at 21:39
  • @Adam If you change it to be "more than *a* person", I think I would have to agree. And now I'm getting *too* close to being flagged as *chatty* myself. Oh well. – Lasse V. Karlsen Jul 19 '11 at 21:40
  • Jon, what about creating a separate class to encapsulate this behavior? – Can Gencer Jul 19 '11 at 21:56
  • @Can: I think it would depend an awful lot on the situation. – Jon Skeet Jul 19 '11 at 22:36
4

You cannot. You can create a method like this though

public void SetClientId(string clientId)
{
    this.ClientID = Convert.ToInt32(clientId);
}
Bala R
  • 107,317
  • 23
  • 199
  • 210
2

You can't pass a string to a property which is declared as integer. You could use a method instead.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
2

I recommend you don't try. You're only causing headaches for a later date.

Add an additional setter, instead...

public string ClientIDText
{
    set
    {
        clientID = int.Parse(value);
    }
}

or create a SetClientID(string) method.

There is an advantage to create a SetClientID method; you can create overloads, so you could create

SetClientID(int)
SetClientID(string)
etc.

However, I still think you're building ambiguity into your app for the convenience of saving a few lines of code.

Steve Morgan
  • 12,978
  • 2
  • 40
  • 49
  • I think that's a better approach – Tocco Jul 19 '11 at 21:28
  • 1
    Don't do this as this breaks encapsulation.. see my answer. – Can Gencer Jul 19 '11 at 21:52
  • I'd agree to a very limited extent that it would be better to set ClientID rather than clientID in case there are additional rules. But unless ClientID is relevant elsewhere, I would argue against it breaking encapsulation. – Steve Morgan Jul 19 '11 at 21:58
2

Alternatively, you can provide a ClientID class that has implicit conversion between itself, int and string, then you can have a property:

public ClientIdType ClientId
{
    get; set;
}

But all the callers could then use it thus:

var myClass = new MyClass();
myClass.ClientId = 1;
myClass.ClientId = "2";

int id = myClass.ClientId;

http://msdn.microsoft.com/en-us/library/85w54y0a.aspx

However, this seems like a lot of legwork just to make it easier for the caller, but it's still an option.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
1

I think the cleanest solution is, as some others have suggested is to create a ClientId class. I don't think this is necessarily bad, as this post explains in a pretty good way:

Many classes have a tendency to consume or expose primitive values like integers and strings. While such primitive types exist on any platform, they tend to lead to procedural code. Furthermore they often break encapsulation by allowing invalid values to be assigned.

Having a seperate class gives you different sorts of possibilities to validate the the id as well, if that is a requirement. In the end, it is all about encapsulation.

Something like this should get you started:

//auto-property for your class
public ClientId ClientID
{
   get; set;
}

And the ClientId class:

public class ClientId
{
  private int _id;

  public ClientId(int id) { _id = id; }
  public ClientId(string id) { //convert id to int, throw exception if invalid }

  public int Value { return _id; }
}

Don't forget to implement Equals and GetHashCode as well, which can be done trivially for this class.

Can Gencer
  • 8,822
  • 5
  • 33
  • 52
  • An interesting approach, but it seems to introduce little but overhead over the other recommended answers _unless_ ClientID (and this behaviour) is reused elsewhere. At the end of the day, there's a pragmatic decision to be made between using primitives and defining classes for everything. – Steve Morgan Jul 19 '11 at 22:00
  • @Steve, I think from the perspective of pureness, it is the best solution, but I guess in a practical sense it might not be as you said. But the question asker should make that call, and as Mark Seeman points out primitives can easily get abused in code, so it is good to have some general awareness of that. – Can Gencer Jul 19 '11 at 22:03
  • Indeed. It's always better to be able to decide one way or the other form a position of knowledge than one of ignorance. Good contribution. – Steve Morgan Jul 19 '11 at 22:06
  • In essence, he is saying that an Id can be represented as both a string and int, and that sounds like some encapsulation is needed there to me and what he is experiencing with needing two setters is a code smell. Reminded me of a class like GUID for example (where it is not just a string..). – Can Gencer Jul 19 '11 at 22:09
  • My guess is that he's reading values in from a text stream and doesn't want to bother parsing the value, which if true, is definitely a code smell. I'd be interested to know. – Steve Morgan Jul 19 '11 at 22:12
0

How about as an alternative in the property:

    private int rowValue_;
    public object RowValue
    {
        get
        {
            return this.rowValue_;
        }
        set
        {
            var type = value.GetType();
            if (type == typeof(string))
            {
                this.rowValue_ = Convert.ToInt32(value);
            }
            else if (type == typeof(int))
            {
                this.rowValue_ = (int)value;
            }
            else
            {
                throw new InvalidDataException(
                    "HandwritingData RowValue can only be string or int. 
                    Passed in parameter is typeof {0}",
                    value.GetType().ToString());
            }
        }
    }

It works for me as well as trapping bad parameters.

Regards, Chris

Chris Wegener
  • 95
  • 1
  • 3
0

In this example How Can I inherit the string class? there is a nice contribution by René if you can stand having a property not being a pure string - but serve as one and be able to cast:

class Foo {
    readonly string _value;
    public Foo(string value) {
        this._value = value;
    }
    public static implicit operator string(Foo d) {
        return d.ToString();
    }
    public static implicit operator Foo(string d) {
        return new Foo(d);
    }
}
Community
  • 1
  • 1
tofo
  • 388
  • 3
  • 8
0

You can't overload properties, so that won't work.

What you can do is

  1. Just convert the thing to an int before setting it (preferred)
  2. Create a method to do the conversion from clients, i.e., SetClientIdFromString(strign id ).
Ed S.
  • 122,712
  • 22
  • 185
  • 265