views:

74

answers:

2

I have a class that returns an object type to a variable. The variable Must know what the real type is when operations are performed on it:

public object Data 
    {
        get
        {
            switch (CriteriaID)
            {
                case (int)matrix2.enums.NodeTypeEnums.Enums.MultiLineText:
                    return (string)_Data;
                case (int)matrix2.enums.NodeTypeEnums.Enums.SingleLineText:
                    return (string)_Data;
                case (int)matrix2.enums.NodeTypeEnums.Enums.Number:
                    int temp = 0;
                    return int.TryParse((string)_Data, out temp) ? (int?)temp : null;
                case (int)matrix2.enums.NodeTypeEnums.Enums.Price:
                    decimal temp1 = 0;
                    return decimal.TryParse((string)_Data, out temp1) ? (decimal?)temp1 : null;
                case (int)matrix2.enums.NodeTypeEnums.Enums.PullDown:
                    return (string)_Data;
                case (int)matrix2.enums.NodeTypeEnums.Enums.Checkbox:
                    bool temp2 = false;
                    return bool.TryParse((string)_Data, out temp2) ? (bool?)temp2 : null;
                case (int)matrix2.enums.NodeTypeEnums.Enums.Date:
                    DateTime temp3 = DateTime.MinValue;
                    return DateTime.TryParse((string)_Data, out temp3) ? ((DateTime?)temp3).Value.ToString("MM/dd/yyyy") : null;
                case (int)matrix2.enums.NodeTypeEnums.Enums.Link:
                    return (string)_Data;
                case (int)matrix2.enums.NodeTypeEnums.Enums.Image:
                    return (string)_Data;
                default:
                    return (string)_Data;
            }
        }
        set
        {
            _Data = value;   
        }
    }

The data property is used like this:

temp.Count() > 0 ? temp.FirstOrDefault().Data : " "

Using it like this works but I am not sure if this is the best implementation and/or the most efficient. Is their a better way to do this?

+1  A: 

To be honest, seeing as your dealing with a finite number of possible results, you might as well stick to using a switch statement. What I would do, is change a lot of what you are doing...

Firstly, don't put any complex operations with getters or setters. You should push these out to a seperate method:

public object Data
{
  get
  {
    return FormatData(_Data);
  }
}

Secondly, you don't need to cast in your case blocks:

case (int)matrix2.enums.NodeTypeEnums.Enums.MultiLineText:

Thirdly,

temp.Count() > 0 ? temp.FirstOrDefault().Data : " "

...there are a few issues here to, for instance:

temp.Count() > 0

...will cause the entire enumerable to be enumerated, its much more efficient to do:

temp.Any()

...as it will return after it encounters the first element, next:

temp.FirstOrDefault().Data

if you are calling .Count() > 0 (or now hopefully .Any()), you can change this to .First(), as you've already established that there must be an instance for it to hit this logic path.

temp.FirstOrDefault().Data : "&nbsp";

Because your method potentially returns types other than string, the result of the complete tertiary operation can only be assigned to Object, because the compiler won't know which argument type it can be assigned to....imagine you are returning an Int32 or a String, which one?

UPDATE Now I think about it, a really important change you should make is simply:

public object Data { get; set;}

The property should really just return the raw data. It should be outside the problem domain of the model that you present the data (and hence convert it into other types).

It looks like you are essentially writing the object out to html, so why all the work to do with formatting it? For the most part you can use .ToString() to get the string representation of the object:

temp.Any() ? temp.First().Data.ToString() : "nbsp;"
Matthew Abbott
Wow..I have changed all my count > 0 to any..Thanks. Is there an elegant to implement your last advise?
Luke101
See updated answer
Matthew Abbott
Thank you..your suggestion worked
Luke101
A: 

Assuming that your origin type is compatible with the destination type, you can do something like this:

public T ConvertValue<T>(object value)
{
    return (T)Convert.ChangeType(value, typeof(T), null);
}

(Or if you have the Convert.ChangeType overload that does not require the IFormatProvider)

public T ConvertValue<T>(object value)
{
    return (T)Convert.ChangeType(value, typeof(T));
}

And then consume it by doing

int myValueConvertedToInt = ConvertValue<int>("12345");

However, if the types are not compatiable, i.e., you try something like

int myValueConvertedToInt = ConvertValue<int>("XXX");

It will throw. Therefore, you will want to have strong validation in place on the properties you will attempt to convert. I'm partial to the System.ComponentModel.DataAnnotations attributes for attaching validation requirements to properties.

Jon
If the type is an object and I don't know the real type how do i use Convert.ChangeType
Luke101