3

I am attempting to move validation of input data into the get;set; of a class struct.

public void PlotFiles()
    {

     List<DTVitem.item> dataitems;
        DTVitem.item i;
        DateTime.TryParse("2012/01/01", out i.dt);
        DateTime.TryParse("04:04:04", out i.t);
        int.TryParse("455", out i.v);
        dataitems.Add(i);

    }

The struct is declared in a separate class (probably unnecessary):

public partial class DTVitem
{
    public struct item
    {
        public DateTime dt;
        public DateTime t;
        public int v;
    }
}

Every time I set DTVitem.item.dt, DTVitem.item.t, or DTVitem.item.v, I wish it to perform the relevant .TryParse() to validate the property contents.

However, when I attempt to use TryParse() as follows (attempting to wrap my head around this example from MSDN):

public partial class DTVitem
{
    private DateTime _datevalue;

    public string dt
    {
        get { return _datevalue; }
        set { DateTime.TryParse(value, out _datevalue) ;}
    }
}

I receive the error that _datevalue is a DateTime and cannot be converted to a string. The reason is obviously that the return path must return the type of dt in this instance (a string). However, I have attempted to massage this a few different ways, and am not able to hack it.

How do I achieve my goal of validating a string value as a DateTime when setting it as a property of an instance of the struct?

Is using set as I am attempting to the best way?

I can see that there is a lot of value in using get;set; for validation and would really like to understand it.

Thanks very much,

Matt

[edit]

Thanks to Jon Skeet below for pointing out the err of my ways.

Here's another thread on problems with mutable structs, and another speaking about instantiating a struct. Note structs are value types.

I believe the rest of what he was pointing out is sort of just agreeing that burying the struct way far away isn't necessary, and I should review why I'm doing it.

[solution]

I've taken into account some recommendations below and come up with the following:

public partial class DTVitem
{
    private DateTime _dtvalue, _tvalue;
    private int _vvalue;

    public string dt
    {
        get { return _dtvalue.ToString(); }
        set { DateTime.TryParse(value, out _dtvalue); }
    }

    public string t
    {
        get { return _tvalue.ToString(); }
        set { DateTime.TryParse(value, out _tvalue); }
    }

    public string v
    {
        get { return _vvalue.ToString(); }
        set { int.TryParse(value, out _vvalue); }
    }
}

Inside my program class, I've instantiated and set with the following:

DTVitem item = new DTVitem();
item.dt = "2012/01/01";
item.t = "04:04:04";
item.v = "455";

So I opted not to use a struct, but a class; or really an instance of the class.

Community
  • 1
  • 1
brandeded
  • 2,080
  • 6
  • 25
  • 52
  • 6
    It's extremely unclear why you've got a public mutable struct with public fields as a nested type within `DTVitem`. All of those seem like a bad idea to me. – Jon Skeet Feb 19 '13 at 21:27
  • 2
    Your error is because you're returning a `DateTime` in the `get` for a property that is declared as a `string`. – juharr Feb 19 '13 at 21:29
  • 1
    Get and Set should only get and set a variable. It sounds like a class would be more useful to you than a struct, at least the way you are using it. The piece calling set should be responsible for using a valid DateTime not the struct/class. – Ryan Gates Feb 19 '13 at 21:30
  • 1
    @RyanGates Not true at all. You can encapsulate functionality in a property, including validation. There's not reason to copy the validation code around or put calls to it everywhere you set the property – Sten Petrov Feb 19 '13 at 21:32
  • Thanks John for pointing out the terrible flaw. I'm not a dev by trade, so I'm "full-steam-ahead"ing this. I'll look into that, as it's clearly a fundamental flaw. You might be more constructive and advise on more detail, unless the detail is so huge that I can refer back to my last sentence. Thanks Ryan, I'll look in that direction. – brandeded Feb 19 '13 at 21:34

5 Answers5

5

A property can only have one type. If you want the property to be of type string, then you can implement it this way:

public partial class DTVitem
{
    private DateTime _datevalue;

    public string dt
    {
        get { return _datevalue.ToString(); }
        set { DateTime.TryParse(value, out _datevalue) ;}
    }
}

However, using TryParse() will mean that the setter will not throw an exception if the DateTime is invalid. If you want it to do this, use DateTime.Parse() instead.

Oren Melzer
  • 749
  • 4
  • 7
1
public partial class DTVitem
{
    private DateTime _datevalue;

    public string dt
    {
        get { return _datevalue.ToString(); }
        set { DateTime.TryParse(value, out _datevalue) ;}
    }
}
Sten Petrov
  • 10,943
  • 1
  • 41
  • 61
1

You're just missing a type convertion in the get. _datevalue is a DateTime but your property's a string.

get { return _datevalue.ToString(); } //or .toShortDateString() or ToShorttimeString()
0xFF
  • 808
  • 1
  • 12
  • 33
0

The get;set; must have the same type. Your get returns a datetime when it expects a string, hence the error.

just use an explicit method bool setDate(String datestring) and put your code there. You can return a bool from the tryparse to let you know if it was successful.

0

Other (design mostly) issues aside, just getting to the problem of returning _datevalue as string, you can simply do something like:

public string dt
{
    get { return _datevalue.ToString(); }
    set { if(!DateTime.TryParse(value, out _datevalue)) /* Error recovery!! */ ;}
}

>>> You may also want to check the docs for DateTime.ToString() and see what format you want to get your string in when accessing the property.

Mau
  • 14,234
  • 2
  • 31
  • 52