使用泛型乘以整数

时间:2014-02-06 06:30:34

标签: c# .net generics

我有一个名为GenericItem的类(第一次使用泛型),假设我想将两个项目相乘,如果它们是整数类型,你可以看到我在方法returnCounterMultiply中尝试它,但它虽然我试图转换它们并检查它们是否为整数类型,但是不允许我将它们相乘。

namespace Components
{
    public class GenericItem<T>
    {
        private T data;
        private T counter;

        public T Data
        {
            get { return data; }
            set { data = value; }
        }

        public GenericItem(){}
        public GenericItem(T _data)
        {
            data = _data;
        }

        public T returnCounterMultiply(T value)
        {
            int c = 0;
            int d = 0;
            if (counter.GetType() == typeof(int) && value.GetType() == typeof(int))
            {
              //cant multiply two of type T, why if i am converting to int?.
               return (T)Convert.ChangeType(counter, typeof(Int32)) * (T)Convert.ChangeType(value, typeof(Int32));
            }
            return value;
        }

    }
}

我很感激对此的一些解释,因为这是我第一次开展这项工作(这只是一个用于理解这个GENERICS INTRO和此GENERICS CLASSES的示例课程,但仍然无法理解它

6 个答案:

答案 0 :(得分:2)

在我看来,在这种情况下使用泛型是一种矫枉过正的行为。

通用约束支持以下内容会很好:

// T parameter is a type which overloads "+" operator...
where T : +

在你的具体案例中,我会说你以错误的方式行事。为什么不创建一个类来实现类型为int的数学运算?

T参数(或任何其他参数,当然......)可以被约束为接收具有以下类型的类型时,泛型更好地工作:

  • 公共无参数构造函数。
  • 继承或实现类/接口
  • 您需要约束T必须是类而不是结构...

当你使用泛型需要进行类型转换时遇到问题时,我相信你已经打败了泛型!

答案 1 :(得分:2)

你的问题与泛型无关,但基本的C#强制转换:

//cant multiply two of type T, why if i am converting to int?.
return
  (T)Convert.ChangeType(counter, typeof(Int32)) 
  *
  (T)Convert.ChangeType(value,typeof(Int32));

你没有乘以int但是T - 和T是泛型类型你只能使用在你的泛型约束中定义的方法,你没有,所以没有相乘。

如果你想乘以int,那么这样做:

  (T) (
     ((Int32)Convert.ChangeType(counter, typeof(Int32)))
     *
     ((Int32)Convert.ChangeType(value,typeof(Int32)))
  );

看到区别?

基本上在你的代码中你在乘法中处理T,这里我处理Int32。事实上,如果T是Int32(正如你之前在IF语句中测试的那样),你可以跳过转换和转换:

  (T) (
     ((Int32)counter)
     *
     ((Int32)value)
  );

现在,仿制药是数学的一个不好的例子,因为你不能在泛型上使用操作 - 遗憾的是。这是对这个概念的滥用,但我认为这是一个学习练习,因此我的答案集中在那一部分。

答案 2 :(得分:2)

我看不到你想要实现的目标,但如果你必须这样做,我认为你必须使用一个界面:

public interface IMultiplyable<T>
{
    T Multiply(T x);
}

public class Int : IMultiplyable<Int>
{
    private int _data { get; set; }

    public Int(int data)
    {
        _data = data;
    }

    public Int Multiply(Int x)
    {
        return new Int(_data * x._data);
    }

    public override string ToString()
    {
        return _data.ToString();
    }
}

public class GenericItem<T> where T : IMultiplyable<T>
{
    private T data;
    private T counter;

    public T Data
    {
        get { return data; }
        set { data = value; }
    }

    public GenericItem() { }
    public GenericItem(T _data)
    {
        data = _data;
    }

    public T returnCounterMultiply(T value)
    {
        return Data.Multiply(value);
    }

    public override string ToString()
    {
        return Data.ToString();
    }
}

用法:

        var a = new GenericItem<Int>(new Int(4));
        MessageBox.Show(a.returnCounterMultiply(new Int(5)).ToString()); //20

答案 3 :(得分:1)

您可以这样做:

public class GenericItem<T>
{
    private T data;

    public T Data
    {
        get { return data; }
        set { data = value; }
    }

    public GenericItem(){}
    public GenericItem(T _data)
    {
        data = _data;
    }

    private Dictionary<Type, Delegate> operations =
        new Dictionary<Type, Delegate>()
        {
            { typeof(int), (Func<int, int, int>)((x, y) => x * y) },
            { typeof(string), (Func<string, string, string>)((x, y) => x + " " + y) },
        };

    public T returnCounterMultiply(T value)
    {
        if (operations.ContainsKey(typeof(T)))
        {
            var operation = (Func<T, T, T>)(operations[typeof(T)]);
            return operation(data, value);
        }
        return value;
    }
}

你只需要在字典中为每个你想要使用的有效类型定义一个操作,它就可以在没有任何类型转换的情况下工作(除了转换为Func)。

我有这些测试结果:

var gii = new GenericItem<int>(42);
var xi = gii.returnCounterMultiply(2);
// xi == 84

var gis = new GenericItem<string>("Foo");
var xs = gis.returnCounterMultiply("Bar");
// xs == "Foo Bar"

答案 4 :(得分:0)

我也尝试了一次,并且必须发现没有很好的方法来使用泛型。你不能像在C ++中那样通用。

作为替代方案,您可以包装数据类型并使用通用接口:

interface IMathOps
{
    object Value { get; }

    void Add(IMathOps other);
    // other methods for substraction etc.
}

class IntWrapper : IMathOps
{
    public int value;

    public void Add(IMathOps other)
    {
        if(other is IntWrapper)
        {
            this.value += (int)other.Value;
        }
    }

    public object Value { get { return this.value; } }
}

// class FloatWrapper : IMathOps ...

答案 5 :(得分:-3)

我认为你应该使用where (generic type constraint)。因此,如果T不是int,它将在编译时给出错误。

public T returnCounterMultiply(T value)  where T : int
{
    int c = 0;
    int d = 0;

    return c*d;
}