01/10/2018, 16:07

Lỗi vô cùng khó hiểu: Cannot use an expression of type 'byte*' as an argument to a dynamically dispatched operation

Mình có đoạn code này:

unsafe public Task<object> uncompress16(dynamic input)
{
  var inputHexAddress = Convert.ToUInt64((string)input.inputHexAddress, 16);
  if (inputHexAddress == 0) throw new ArgumentException("Hex address is in invalid form!");
  var outputGetter = (Func<object, Task<object>>)input.outputGetter;
  var inputArr = (byte*)(new UIntPtr(inputHexAddress).ToPointer());
  var inputLen = (int)input.inputLen;
  var compressedData = new UnsafeArray(inputArr, inputLen);
  int size = (int)compressedData[1] + ((int)compressedData[2] << 8) + ((int)compressedData[3] << 16);
  return outputGetter(size).ContinueWith<object>(uncompress16_stage2);
}
unsafe private object uncompress16_stage2(Task<object> lastTask)
{
  var output = (dynamic)lastTask.Result;
  var outputHexAddress = Convert.ToUInt64((string)output.outputHexAddress, 16);
  if (outputHexAddress == 0) throw new ArgumentException("Hex address is in invalid form!");
  var outputArr = (byte*)(new UIntPtr(outputHexAddress).ToPointer());
  var outputLen = output.outputLen;
  var uncompressedData = new UnsafeArray(outputArr, outputLen);
  return output;
}

Kết quả là dòng này:

var uncompressedData = new UnsafeArray(outputArr, outputLen);

Báo lỗi:

Cannot use an expression of type 'byte*' as an argument to a dynamically dispatched operation.

Nhưng dòng này:

var compressedData = new UnsafeArray(inputArr, inputLen);

Lại không sao cả:

Đây là class UnsafeArray:

public class UnsafeArray
{
  unsafe private byte* _array;
  unsafe private int _len;
  unsafe public UnsafeArray(byte* array, int len)
  {
    if (array == null) throw new NullReferenceException("Array is null!");
    if (len < 0) throw new ArgumentOutOfRangeException("Array length cannot be negative!");
    this._array = array;
    this._len = len;
  }
  unsafe public byte this[int key]
  {
    get
    {
      if (key < 0 && key >= _len) throw new ArgumentOutOfRangeException("Index of array is out of bound.");
      return _array[key];
    }
    set
    {
      if (key < 0 && key >= _len) throw new ArgumentOutOfRangeException("Index of array is out of bound.");
      _array[key] = value;
    }
  }
}
viết 18:14 ngày 01/10/2018

Google cái lỗi CS1978 ra thớt này bên SO: https://stackoverflow.com/questions/5418428/error-cs1978-cannot-use-an-expression-of-type-uint-as-an-argument-to-a-dynam

(đưa lỗi đưa luôn cái error code lên đưa cái error message ko google mãi ko ra @_@)

In unsafe code (§27), a type-argument shall not be a pointer-type

có người bảo là xài đỡ boxing pointer:

I repeated my comment here just to be able to post some code, as one of the solution might be to use IntPtr. It works but you lose part of the type info so I don’t know if it’s really useful.

It avoid loosing type safety creating an IntPtr struct may allow to use dynamics, in this case the T type would only be a marker for the DLR. But maybe it’s overkill to do this just to be able to use the DLR with pointers.

vậy thay vì truyền byte* vào ctor của UnsafeArray bây giờ ta truyền thẳng UIntPtr luôn:

unsafe public UnsafeArray(UIntPtr arrayPtr, int len)
{
    if (arrayPtr.ToPointer() == null) throw new NullReferenceException("Array is null!");
    if (len < 0) throw new ArgumentOutOfRangeException("Array length cannot be negative!");
    this._array = (byte*)arrayPtr.ToPointer();
    this._len = len;
}

...
var inputArr = new UIntPtr(inputHexAddress); //sửa tên lại inputArrPtr?
...
var outputArr = new UIntPtr(outputHexAddress); //sửa tên lại outputArrPtr?

compile đuợc nhưng chạy đúng hay ko thì ko biết @_@

Văn Dương viết 18:11 ngày 01/10/2018

Truyền IntPtr hoặc UIntPtr vào ctor, sau đó trong ctor mới cast IntPtr hoặc UIntPtr qua byte*.

明玉 viết 18:12 ngày 01/10/2018

var outputLen = output.outputLen;

Sorry mọi người, bug nằm ở đây, đáng ra phải là:

var outputLen = (int)output.outputLen

Compiler nó báo lỗi sai chỗ (nó lại báo lỗi ở outputArr) nên mình không nhận ra cái này.

Văn Dương viết 18:19 ngày 01/10/2018

Không biết mọi người thế nào, nhưng mình rất ngại dùng var. Bởi vì nó nhận nhiều loại biến nên nó rất khó bắt lỗi syntax. Không tóm được lỗi syntax thì rất dễ ăn lỗi runtime. Debug lỗi runtime nhọc lắm @@.

Bài liên quan
0