Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic C# Class: Set "Generic" Property

Tags:

c#

types

generics

I'm quite new to C#, so I might have a problem that C# has a simple solution for. I have a generic class with a property of "generic" type. I want to have a function to set that property, but I need to convert it to do so.

public class BIWebServiceResult<T>
{
    public T Data;

    public delegate StatusCode StringToStatusCode(string Input);

    public void SetData(string Input, StringToStatusCode StringToError)
    {
        if (StringToError(Input) == 0)
        {
            if (Data is string[])
            {
                Data = new string[1];
                Data[0] = Input;
            }
            else if (Data is string)
            {
                Data = Input;
            }
            else if (Data is bool)
            {
                Data = DetectBool(Input);
            }
        }
    }

    private bool DetectBool(string Compare)
    {
        return Compare == "true";
    }
}

The problem with that approach is, that it does not work :)

(No that's not all code, just a snippet to show what my problem is)

It doesn't even compile, because "Data = new string[]" can't work if Data is - for example - boolean.

How do I implement a function that behaves differently depending on the type of my generic property?

like image 604
BlaM Avatar asked Jan 02 '26 09:01

BlaM


1 Answers

You want a generic class, but you're changing its behavior based on its generic type argument.

Since this behavior is specialized according to T, you should really make your generic class an abstract base from which to derive specialized subclasses:

public abstract class BIWebServiceResult<T>
{
    public T Data { get; set; }

    public delegate StatusCode StringToStatusCode(string Input);

    public abstract void SetData(string Input, StringToStatusCode StringToError);
}

Then you might have, for example:

public class BIWebServiceStrArrayResult : BIWebServiceResult<string[]>
{
    public override void SetData(string Input, StringToStatusCode StringToError)
    {
        if (StringToError(Input) == 0)
        {
            Data = new string[1];
            Data[0] = Input;
        }
    }
}

Personally, though, I'd be inclined to do away with all this manual string manipulation altogether and leave the job of parsing input to whatever code is calling this method:

// This is the same signature used by, e.g., int.TryParse, double.TryParse, etc.
public delegate bool Parser<T>(string input, out T output);

public void SetData(string Input, Parser<T> parser)
{
    T value;
    if (parser(Input, out value))
        Data = value;
}

By the way, typically it's not really necessary to define your own delegates when the same signature is already available in the form of an Action* or Func*. In the case of your StringToStatusCode, this could simply be defined as a Func<string, StatusCode>. (But I would still personally recommend something like the last bit of code I posted instead.)

like image 91
Dan Tao Avatar answered Jan 03 '26 22:01

Dan Tao



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!