Reputation: 11926
For example, as an overloaded []
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;
}
}
}
and compiler complains(underlines) about it "cannot take address of ..." to a managed type T
.
I know T
will be only float,double,int or byte in runtime but I don't know how to tell this to compiler so it trusts me.
Why can't I use it, all are pointers anyway, I can overflow any type of array if I'm not careful.
How can I achieve this(with a similar way or another) 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 don't just care about performance here, but also code simplicity too. (one code for all T types) Interfaces can't help here I suppose.
Upvotes: 4
Views: 1196
Reputation: 726969
C# restricts pointer types to
sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
, or bool
,enum
type,struct
type that contains fields of unmanaged types only.That last point is key, because the compiler must be able to verify that the struct
to which you are trying to make a pointer is "legal". Otherwise, you would be able to pass T
that is a struct
with fields referencing managed types (say, a string
) which is prohibited.
Since you are interested in providing this behavior for four data types, you should be able to address 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
The run-time efficiency will remain the same, assuming that the compiler has enough information to resolve overloads at compile time.
Upvotes: 3