简体   繁体   中英

How does one use overloaded operators with Generics in C#?

I'm making an attempt to write a class for storing, processing, saving and loading data. I hope that when I finally finish it, it will simplify and mostly automate the process of organizing large numbers of fields, saving them to files and later retrieving them from those files.

My first thought was to use dynamics, but I didn't like the performance drop of even one dynamic, and the class in its original form had many dynamics. I figured I would eliminate all of that and just use generics, which does make things a bit smoother. It also reduces the amount of required code. However, I have run into a new problem. I'm trying to overload operators to make the manipulation of the values a little bit easier.

It's set up like this:

public class DataElement<T>
{

        public T In;
        public T Out;

}

That's an extremely simplified and watered down version, but it is enough for what I'm currently struggling with. Here's the problem:

        public static DataElement<T> operator +(DataElement<T> d, T val)
        {
            object o = val;
            object oo = d.Out;
            if (typeof(T) == typeof(string))
            {
                string s = o.ToString();
                s += oo.ToString();
                oo = s;
            }
            else
            {
                if (typeof(T) == typeof(int))
                {
                    int i = int.Parse(o.ToString());
                    i += int.Parse(oo.ToString());
                    oo = i;
                }
                else if (typeof(T) == typeof(float))
                {
                    float f = float.Parse(o.ToString());
                    f += float.Parse(oo.ToString());
                    oo = f;
                }
                else if (typeof(T) == typeof(long))
                {
                    long l = long.Parse(o.ToString());
                    l += long.Parse(oo.ToString());
                    oo = l;
                }
                else if (typeof(T) == typeof(char))
                {

                }
            }
            d.Out = (T)oo;
            return d;
        }

I'm not even sure if that's going to work. I haven't tested it yet. Mostly because I don't like it. All those IF statements. It's ugly and clunky. The ideal solution would be to use a SWITCH statement, but oh no. VS tells me that SWITCH statements for Types is only supported in the absolute newest versions of C#. And I can't think of any other way to do it. If I try directly, like this:

    d.Out += val;

VS tells me "Operator '+=' cannot be applied to operands of type 'T' and 'T'" Okay, then. How does one accomplish what I'm trying to do? When I had "val" set to "int" instead of generic "T", it told me the same thing. Is there something I'm missing? Am I reinventing the wheel here?

If you are stuck with an older version you can cast T to TOther like so: (TOther)(object)o .

if (typeof(T) == typeof(int)) {
    int i = (int)(object)o;
    ...

The real solution to this problem would be to use generic constraints to restrict T to a type that support addition. Unfortunately there no common interface for the integral numeric types, but there are threads with a long list of workarounds .

My suggestion would be to delegate the problem to the caller, ie

public DataElement<T> Add(T val, Func<T, T, T> addMethod){
       return new DataElement<T>{In = this.In, Out = addMethod(this.Out, val)};
}

Note that this uses a regular method instead of an operator, since operators has to fulfill some specific rules. I would also be very careful with mutating the input objects, I would usually expect basic methods like 'add' to return a new object, and not to modify the input objects.

However, if the goal is

write a class for storing, processing, saving and loading data

Then I would suggest using a serialization library, at least for the "storing, saving and loading" parts. Since these are purpose made for converting objects to a serialized form that can be saved to disk or sent over the network etc. Json.Net is a popular alternative, but there are many other alternatives.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM