【问题标题】:Operator Overloading For Builtin Types内置类型的运算符重载
【发布时间】:2009-03-06 09:12:39
【问题描述】:

如何覆盖运算符以用于字符串、数组等内置类型?例如:我希望覆盖数组 + 运算符的含义。

【问题讨论】:

    标签: c#


    【解决方案1】:

    基本上你不能。

    您可以使用扩展方法来添加如下功能:

    public void CustomAdd( this Array input, Array addTo ) {
        ...
    }
    

    但这不适用于运营商。

    【讨论】:

    • 不应该在内置类型或扩展方法上使用运算符重载吗?
    • 是的 - 即使你可以这样做,它也会导致非常混乱的代码:“为什么这个数组不能像往常一样工作?”
    【解决方案2】:

    您不能为现有类型重载运算符,因为这可能会破坏使用这些类型的任何其他代码。

    您可以创建自己的类来封装数组,从数组中公开您需要的方法和属性,并重载任何有意义的运算符。

    例子:

    public class AddableArray<T> : IEnumerable<T> {
    
        private T[] _array;
    
        public AddableArray(int len) {
            _array = new T[len];
        }
    
        public AddableArray(params T[] values) : this((IEnumerable<T>)values) {}
    
        public AddableArray(IEnumerable<T> values) {
            int len;
            if (values is ICollection<T>) {
                len = ((ICollection<T>)values).Count;
            } else {
                len = values.Count();
            }
            _array = new T[len];
            int pos = 0;
            foreach (T value in values) {
                _array[pos] = value;
                pos++;
            }
        }
    
        public int Length { get { return _array.Length; } }
    
        public T this[int index] {
            get { return _array[index]; }
            set { _array[index] = value; }
        }
    
        public static AddableArray<T> operator +(AddableArray<T> a1, AddableArray<T> a2) {
            int len1 = a1.Length;
            int len2 = a2.Length;
            AddableArray<T> result = new AddableArray<T>(len1 + len2);
            for (int i = 0; i < len1; i++) {
                result[i] = a1[i];
            }
            for (int i = 0; i < len2; i++) {
                result[len1 + i] = a2[i];
            }
            return result;
        }
    
        public IEnumerator<T> GetEnumerator() {
            foreach (T value in _array) {
                yield return value;
            }
        }
    
        IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return _array.GetEnumerator();
        }
    
    }
    

    用法:

    // create two arrays
    AddableArray<int> a1 = new AddableArray<int>(1, 2, 3);
    AddableArray<int> a2 = new AddableArray<int>(4, 5, 6);
    
    // add them
    AddableArray<int> result = a1 + a2;
    
    // display the result
    Console.WriteLine(string.Join(", ", result.Select(n=>n.ToString()).ToArray()));
    

    (请注意,由于该类实现了IEnumerable&lt;T&gt;,因此您可以在其上使用Select 等扩展方法。)

    【讨论】:

    • 这是很多代码,所以 a1 + a2 = 统一数组。为什么不只做 a1.Union(a2).ToArray()
    • 是的,这要简单得多,但效率不高。不过还算不错,快速测试表明它只需要大约 2-4 倍的时间。
    【解决方案3】:

    你不能:)

    但是,对于数组示例,您可以从 IEnnumerable 或 List ... 继承并覆盖这些运算符。

    【讨论】:

      【解决方案4】:

      正如@Keith 指出的那样,简短的回答是你不能。

      更长的答案是,要为类添加运算符重载,您需要能够更改该类的源代码。

      在添加运算符来处理两种不同类型(例如数组 + 字符串)的组合的情况下,您可以更改其中一种类型的源代码就足够了。这意味着您应该能够添加代码来指定如果您将自己的一种类型添加到数组中会发生什么。

      在 BCL 类的情况下,你运气不好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-19
        • 1970-01-01
        • 2016-01-25
        • 1970-01-01
        • 2015-01-29
        相关资源
        最近更新 更多