【问题标题】:C# Extend array type to overload operatorsC# 扩展数组类型以重载运算符
【发布时间】:2010-12-20 18:02:49
【问题描述】:

我想创建自己的类扩展整数数组。那可能吗?我需要的是整数数组,可以通过“+”运算符添加到另一个数组(每个元素添加到每个数组),并通过“==”进行比较,因此它可以(希望)用作字典中的键。

问题是我不想为我的新类实现整个 IList 接口,而只是将这两个运算符添加到现有数组类中。

我正在尝试做这样的事情:

class MyArray : Array<int>

但它显然不是那样工作的;)。

对不起,如果我不清楚,但我正在寻找解决方案几个小时......

更新:

我尝试过这样的事情:

class Zmienne : IEquatable<Zmienne>
{
    public int[] x;
    public Zmienne(int ilosc)
    {
        x = new int[ilosc];
    }
    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }
        return base.Equals((Zmienne)obj);
    }
    public bool Equals(Zmienne drugie)
    {
        if (x.Length != drugie.x.Length)
            return false;
        else
        {
            for (int i = 0; i < x.Length; i++)
            {
                if (x[i] != drugie.x[i])
                    return false;
            }
        }
        return true;
    }

    public override int GetHashCode()
    {
        int hash = x[0].GetHashCode();
        for (int i = 1; i < x.Length; i++)
            hash = hash ^ x[i].GetHashCode();
        return hash;
    }

}

然后像这样使用它:

Zmienne tab1 = new Zmienne(2);
Zmienne tab2 = new Zmienne(2);
tab1.x[0] = 1;
tab1.x[1] = 1;

tab2.x[0] = 1;
tab2.x[1] = 1;

if (tab1 == tab2)
    Console.WriteLine("Works!");

而且没有效果。不幸的是,我不擅长接口和重写方法:(。至于我尝试这样做的原因。我有一些方程式,例如:

x1 + x2 = 0.45
x1 + x4 = 0.2
x2 + x4 = 0.11

它们还有很多,例如,我需要将第一个方程添加到第二个方程并搜索所有其他方程以找出是否有任何与 x'es 的组合相匹配的结果。

也许我走错了方向?

【问题讨论】:

    标签: c# arrays operators operator-overloading


    【解决方案1】:

    对于单一类型,它很容易封装,如下所示。请注意,作为密钥,您也希望使其不可变。如果你想使用泛型,那就更难了(询问更多信息):

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Text;
    static class Program {
        static void Main() {
            MyVector x = new MyVector(1, 2, 3), y = new MyVector(1, 2, 3),
                     z = new MyVector(4,5,6);
            Console.WriteLine(x == y); // true
            Console.WriteLine(x == z); // false
            Console.WriteLine(object.Equals(x, y)); // true
            Console.WriteLine(object.Equals(x, z)); // false
            var comparer = EqualityComparer<MyVector>.Default;
            Console.WriteLine(comparer.GetHashCode(x)); // should match y
            Console.WriteLine(comparer.GetHashCode(y)); // should match x
            Console.WriteLine(comparer.GetHashCode(z)); // *probably* different
            Console.WriteLine(comparer.Equals(x,y)); // true
            Console.WriteLine(comparer.Equals(x,z)); // false
            MyVector sum = x + z;
            Console.WriteLine(sum);
        }
    }
    public sealed class MyVector : IEquatable<MyVector>, IEnumerable<int> {
        private readonly int[] data;
        public int this[int index] {
            get { return data[index]; }
        }
        public MyVector(params int[] data) {
            if (data == null) throw new ArgumentNullException("data");
            this.data = (int[])data.Clone();
        }
        private int? hash;
        public override int GetHashCode() {
            if (hash == null) {
                int result = 13;
                for (int i = 0; i < data.Length; i++) {
                    result = (result * 7) + data[i];
                }
                hash = result;
            }
            return hash.GetValueOrDefault();
        }
        public int Length { get { return data.Length; } }
        public IEnumerator<int> GetEnumerator() {
            for (int i = 0; i < data.Length; i++) {
                yield return data[i];
            }
        }
        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }
        public override bool Equals(object obj)
        {
             return this == (obj as MyVector);
        }
        public bool Equals(MyVector obj) {
            return this == obj;
        }
        public override string ToString() {
            StringBuilder sb = new StringBuilder("[");
            if (data.Length > 0) sb.Append(data[0]);
            for (int i = 1; i < data.Length; i++) {
                sb.Append(',').Append(data[i]);
            }
            sb.Append(']');
            return sb.ToString();
        }
        public static bool operator ==(MyVector x, MyVector y) {
            if(ReferenceEquals(x,y)) return true;
            if(ReferenceEquals(x,null) || ReferenceEquals(y,null)) return false;
            if (x.hash.HasValue && y.hash.HasValue && // exploit known different hash
                x.hash.GetValueOrDefault() != y.hash.GetValueOrDefault()) return false;
            int[] xdata = x.data, ydata = y.data;
            if(xdata.Length != ydata.Length) return false;
            for(int i = 0 ; i < xdata.Length ; i++) {
                if(xdata[i] != ydata[i]) return false;
            }
            return true;        
        }
        public static bool operator != (MyVector x, MyVector y) {
            return !(x==y);
        }
        public static MyVector operator +(MyVector x, MyVector y) {
            if(x==null || y == null) throw new ArgumentNullException();
            int[] xdata = x.data, ydata = y.data;
            if(xdata.Length != ydata.Length) throw new InvalidOperationException("Length mismatch");
            int[] result = new int[xdata.Length];
            for(int i = 0 ; i < xdata.Length ; i++) {
                result[i] = xdata[i] + ydata[i];
            }
            return new MyVector(result);
        }
    }
    

    【讨论】:

    • 马克,这太棒了。我会对如何使用泛型和/或双打来做到这一点感兴趣。我应该开始一个新问题吗?我想双打只是改变散列函数的一个例子。谢谢。
    【解决方案2】:

    不允许扩展数组类,见参考:http://msdn.microsoft.com/en-us/library/system.array.aspx

    您可以实现 IList(它具有基本方法),或者在您的类中封装一个 Array 并提供转换运算符。

    如果您需要更多详细信息,请告诉我。

    【讨论】:

    • 我会尝试封装。谢谢!
    • 封装几乎总是比继承更可取,尤其是当您想要扩展重要的框架类型时。另请注意,实现 == 不会神奇地使类型在 c# 中的字典中工作(f# 是另一回事),您必须实现 IEquatable 或覆盖 Equals(object) 以及实现 GetHashCode()
    【解决方案3】:

    你不能只使用 List 类吗?这已经通过 AddRange 方法完成了您想要的操作。

    【讨论】:

    • 我不确定他是否不想用这种方式表示一些大数字。
    【解决方案4】:

    实现ienumerable接口

    【讨论】:

      猜你喜欢
      • 2014-10-27
      • 1970-01-01
      • 1970-01-01
      • 2010-09-15
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 2015-06-03
      • 2018-11-27
      相关资源
      最近更新 更多