C#中的C#强制转换异常

时间:2017-03-21 20:39:01

标签: c# object indexing casting overloading

我有一个类,其中一个字段被分配给T类型的数组或一个类型为T的dll对象,它有this [int i]的重载来模仿一个数组(它使用非托管内存并使用重载来访问它)< / p>

    public T this[int i]
    {
        get
        {
            return ((T[])array)[i]; // can't use return array[i] directly
        }
        set { }
    }

当我使用dll对象时,它会抛出强制转换异常。我认为(T[])会触发对象的重载[]而不是转换为float[],但它总是转换为float[]而对象类型为FloatArr public float this[int i]

有没有办法将原始数组视为转换同时将其他自定义类型视为过载触发器?

如果这不可能,如何返回类型T,而返回类型如float可以从一个简单的浮点数组或一些带有重载的自定义类型收集来返回浮点数?我不想一个接一个地添加float,int,byte,double,char,....无论对象字段是C#数组还是带有重载索引器的自定义类型,我都需要类型T才能工作?

我实际需要的是什么:

    // developer supplies here with his/hers own array
    // or this library uses its own fast C++ wrapper with a [] overload
    public object array { get; set; }

    // returns float, int, byte
    public T this[int i]
    {
        get
        {
            return array[i]; // float[], int[], FloatArr[], ...
        }
        set { }
    }

编辑:如果这是一个糟糕的设计模式,请告诉我。我需要这个类来处理一个属性,无论它是C#数组还是带有[]重载的C ++包装器C#dll对象。

编辑-2:以下是我的想法:

MyArr<float> gpu = new MyArr<float>(1024);
gpu.array=new float[1024];
gpu[35]=40;

or


MyArr<float> gpu = new MyArr<float>(1024);
gpu.allocateUnManagedToArray(); // now array field is a custom object
gpu[35]=40;

编辑-3:这是我放入数组字段的自定义类:

public class FloatArr
{
    public float this[int i]
    {
        get
        {
            unsafe
            {
                float* p = (float*)hArr.ToPointer();
                return *(p + i);
            }

        }
        set {
            unsafe
            {
                float* p = (float*)hArr.ToPointer();
                *(p + i) = value;
            }
        }
    }
}

编辑-4:只是因为我不清楚:

  • 我有一个[]重载的类作为数组
  • 但它也有一个字段,有时会给另一个重载[]的类!
  • 现在我只需要其他开发人员,当他们不想要这个课程时,能够提供他们自己的C#阵列。拥有自己的C ++包装器对象。
  • 然后在这两种情况下,我需要从同一字段(浮点数组或带有[]重载的C ++包装器)索引[]

当然,我可以逐个编写float int byte的所有条件,但这需要更长的时间。通用类很简单,应该很容易,但我在这里遗漏了一些我无法看到的东西。当我添加struct数组时,代码将来会增长得更多,所以我无助地需要泛型类。

2 个答案:

答案 0 :(得分:1)

您需要做的不是使用数组,而是使用IList<T>接口。然后,您需要使自定义类实现该接口。

class FloatArr : IList<float>
{
    //(snip)
    // p and hArr's decliration and assignment
    //(snip)

    public float this[int index]
    {
        get
        {
            unsafe
            {
                float* p = (float*)hArr.ToPointer();
                return *(p + i);
            }

        }
        set
        {
            unsafe
            {
                float* p = (float*)hArr.ToPointer();
                *(p + i) = value;
            }
        }
    }

    IEnumerator<float> IEnumerable<float>.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    void ICollection<float>.Add(float item)
    {
        throw new NotImplementedException();
    }

    void ICollection<float>.Clear()
    {
        throw new NotImplementedException();
    }

    bool ICollection<float>.Contains(float item)
    {
        throw new NotImplementedException();
    }

    void ICollection<float>.CopyTo(float[] array, int arrayIndex)
    {
        throw new NotImplementedException();
    }

    bool ICollection<float>.Remove(float item)
    {
        throw new NotImplementedException();
    }

    int ICollection<float>.Count
    {
        get { throw new NotImplementedException(); }
    }

    bool ICollection<float>.IsReadOnly
    {
        get { throw new NotImplementedException(); }
    }

    int IList<float>.IndexOf(float item)
    {
        throw new NotImplementedException();
    }

    void IList<float>.Insert(int index, float item)
    {
        throw new NotImplementedException();
    }

    void IList<float>.RemoveAt(int index)
    {
        throw new NotImplementedException();
    }
}

如果您不需要写入数组并只阅读,您可以使用IReadOnlyList<T>

大大简化课程
class FloatArr : IReadOnlyList<float>
{
    //(snip)
    // p and hArr's decliration and assignment
    //(snip)

    public float this[int index]
    {
        get
        {
            unsafe
            {
                float* p = (float*)hArr.ToPointer();
                return *(p + i);
            }

        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    IEnumerator<float> IEnumerable<float>.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    int IReadOnlyCollection<float>.Count
    {
        get { throw new NotImplementedException(); }
    }
}

然后您的容器类更改为

// developer supplies here with his/hers own array
// or this library uses its own fast C++ wrapper with a [] overload
public IList<T> array { get; set; }

// returns float, int, byte
public T this[int i]
{
    get
    {
        return array[i]; // float[], int[], FloatArr, ...
    }
    set
    {
        array[i] = value;
    }
}

// developer supplies here with his/hers own array
// or this library uses its own fast C++ wrapper with a [] overload
public IReadOnlyList<T> array { get; set; }

// returns float, int, byte
public T this[int i]
{
    get
    {
        return array[i]; // float[], int[], FloatArr, ...
    }
}

答案 1 :(得分:1)

除了实现IList<T>IReadOnlyList<T>之外,您可以使用dynamic关键字来执行运行时绑定而不是编译时绑定。但是,与使用IList<T>IReadOnlyList<T>

相比,这会有更糟糕的表现
// developer supplies here with his/hers own array
// or this library uses its own fast C++ wrapper with a [] overload
public dynamic array { get; set; }

// returns float, int, byte
public T this[int i]
{
    get
    {
        return array[i]; // float[], int[], FloatArr[], ...
    }
    set 
    {
        array[i] = value;
    }
}