简体   繁体   English

如何在 C# 中使用带有 Generics 的重载运算符?

[英]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.我正在尝试编写一个 class 来存储、处理、保存和加载数据。 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.我的第一个想法是使用动态,但我不喜欢一个动态的性能下降,而原始形式的 class 有很多动态。 I figured I would eliminate all of that and just use generics, which does make things a bit smoother.我想我会消除所有这些,只使用 generics,这确实让事情变得更顺畅了。 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.所有这些 IF 语句。 It's ugly and clunky.它又丑又笨重。 The ideal solution would be to use a SWITCH statement, but oh no.理想的解决方案是使用 SWITCH 语句,但哦不。 VS tells me that SWITCH statements for Types is only supported in the absolute newest versions of C#. VS 告诉我,类型的 SWITCH 语句仅在 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. VS 告诉我“运算符 '+=' 不能应用于 'T' 和 'T' 类型的操作数” 好的,然后。 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.当我将“val”设置为“int”而不是通用“T”时,它告诉我同样的事情。 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 .如果您坚持使用旧版本,您可以像这样将 T 转换为 TOther: (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.这个问题的真正解决方案是使用泛型约束将T限制为支持加法的类型。 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.我也会非常小心地改变输入对象,我通常希望像“add”这样的基本方法返回一个新的 object,而不是修改输入对象。

However, if the goal is但是,如果目标是

write a class for storing, processing, saving and loading data编写一个 class 用于存储、处理、保存和加载数据

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.因为这些是为了将对象转换为可以保存到磁盘或通过网络发送等的序列化形式。Json.Net是一种流行的替代方案,但还有许多其他替代方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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