为什么不允许指向泛型类型的指针?

时间:2017-03-21 23:22:41

标签: c# pointers generics

例如,作为重载的[] setter-getter,

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

并且编译器向托管类型T抱怨(强调)关于它“无法获取...的地址”。

我知道T在运行时只会是float,double,int或byte,但我不知道如何告诉编译器,所以它信任我。

为什么我不能使用它,无论如何都是指针,如果我不小心,我可以溢出任何类型的数组。

如何在不慢于:

的情况下实现这一目标(以类似的方式)
    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;
            }
        }
    }

我不仅关心这里的性能,还关注代码简洁性。 (所有T类型的一个代码)我想,接口在这里无法帮助。

1 个答案:

答案 0 :(得分:3)

C#restricts指针类型

  • sbytebyteshortushortintuintlongulongcharfloatdoubledecimalbool
  • 任何enum类型,
  • 任何指针类型,
  • 任何用户定义的struct类型,仅包含非托管类型的字段。

最后一点是关键,因为编译器必须能够验证您尝试制作指针的struct是否“合法”。否则,您将能够传递T struct,该string字段引用被禁止的托管类型(例如,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 )。

由于您有兴趣为四种数据类型提供此行为,因此您应该能够通过提供四个重载来解决此问题:

String fspath = FileSystemStorage.getInstance().getAppHomePath();
String url = "http://example.com/getSomeJSON.php";

ConnectionRequest cr = new ConnectionRequest(url, false);
cr.setDestinationFile(fspath + "mylocalfile.json");
NetworkManager.getInstance().addToQueue(cr);

运行时效率将保持不变,假设编译器有足够的信息在编译时解决重载。