Why is a pointer to generic types not allowed?

For example, as an overloaded []

recipient installer,

    public T this[int i]
    {
        get
        {
            unsafe
            {
                T* p = (T*)hArr.ToPointer(); // hArr is a C++ object pointer(IntPtr)
                return *(p + i);
            }

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

      

and the compiler complains (underscores) this "cannot accept an address ..." into a managed type T

.

I know there T

will only be float, double, int, or byte at runtime, but I don't know how to pass this on to the compiler so that it trusts me.

Why can't I use it, it's pointers anyway, I can overflow any array type if I'm not careful.

How can I achieve this (anyway) without being much slower than:

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

      

I'm not just concerned about performance here, but also the simplicity of the code. (one code for all T types). Interfaces can't help here.

+3


source to share


1 answer


C # limits the types of pointers to

  • sbyte

    , byte

    , short

    , ushort

    , int

    , uint

    , long

    , ulong

    , char

    , float

    , double

    , decimal

    , Or bool

    ,
  • Any type enum

    ,
  • Any pointer type,
  • Any user-defined type struct

    that contains only fields of unmanaged types.

This last point is key, as the compiler needs to be able to verify that what struct

you are trying to make a pointer is "legal". Otherwise, you will be able to pass T

which is struct

, with fields referencing the managed types (say a string

) that are not allowed.



Since you are interested in providing this behavior for four data types, you should solve this problem by providing four overloads:

public int GetInt(int i) {
    unsafe {
        var p = (int*)hArr.ToPointer();
        return *(p + i);
    }
public void SetInt(int i, int val) {
    unsafe {
        var p = (int*)hArr.ToPointer();
        *(p + i) = val;
    }
}
public float GetFloat(int i) {
    unsafe {
        var p = (int*)hArr.ToPointer();
        return *(p + i);
    }
public void SetFloat(int i, float val) {
    unsafe {
        var p = (float*)hArr.ToPointer();
        *(p + i) = val;
    }
}
... // and so on

      

Runtime efficiency remains the same assuming that the compiler has enough information to resolve overloads at compile time.

+2


source







All Articles