views:

359

answers:

4

I'd like to create my own class extending array of ints. Is that possible? What I need is array of ints that can be added by "+" operator to another array (each element added to each), and compared by "==", so it could (hopefully) be used as a key in dictionary.

The thing is I don't want to implement whole IList interface to my new class, but only add those two operators to existing array class.

I'm trying to do something like this:

class MyArray : Array<int>

But it's not working that way obviously ;).

Sorry if I'm unclear but I'm searching solution for hours now...

UPDATE:

I tried something like this:

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;
    }

}

Then use it like this:

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!");

And no effect. I'm not good with interfaces and overriding methods unfortunately :(. As for reason I'm trying to do it. I have some equations like:

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

There are a lot more of them, and I need to for example add first equation to second and search all others to find out if there is any that matches the combination of x'es resulting in that adding.

Maybe I'm going in totally wrong direction?

+4  A: 

Its not permitted to extend the array class, see the reference: http://msdn.microsoft.com/en-us/library/system.array.aspx

You could either implement IList (which has the basic methods), or encapsulate an Array in your class and provide conversion operators.

Please let me know if you need more detail.

Grzenio
I'll try encapsulating then. Thanks!
Episodex
encapsulation is almost always preferable to inheritance, especially when you want to extend a significant framework type.Note also that implementing == does NOT magically make a type work in a dictionary in c# (f# is a different matter) you must implement either IEquatable<self> or overrode Equals(object) as well as implementing GetHashCode()
ShuggyCoUk
In fact Marc has done it all for you - use his answer :)
ShuggyCoUk
A: 

Can you not just use the List class? This already does what you want via the AddRange method.

Paul Ruane
I am not sure if he doesn't want to represent some big numbers this way.
Grzenio
A: 

implement the ienumerable interface

PoweRoy
+2  A: 

For a single type, it is pretty easy to encapsulate, as below. Note that as a key you want to make it immutable too. If you want to use generics, it gets harder (ask for more info):

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);
    }
}
Marc Gravell
Thanks, I'll try this :).
Episodex
very good point about the immutability
ShuggyCoUk
Works now, thanks alot!
Episodex