0

I would like to have a helper method for converting byte array to generic type value:

public static T BytesToValue<T>(byte[] bytes)
{
    int pos = 0;
    T result = default;
    foreach (byte b in bytes)
    {
        //Cannot convert from type byte to T error here
        result |= ((T)b) << pos;
        pos += 8;
    }
    return result;
}

The problem is that the compiler gives the error.

The method will primarily be used for getting int and long values and performance is very critical.

How can this be fixed?

6
  • 3
    Are you trying to implement something like BitConverter.ToInt64(byte[], int)? Commented Oct 6, 2019 at 17:01
  • 1
    This isn't going to work. You also can't apply arithmetic operators to values with generic types, so the << won't work either. Commented Oct 6, 2019 at 17:02
  • May be the answer on this topic helps: stackoverflow.com/questions/33616621/… Commented Oct 6, 2019 at 17:20
  • dymanoid, yes. I'm trying to implement an alternative to BitConverter becuase the latter is slow compared to bitwise operations. Commented Oct 6, 2019 at 18:16
  • @yaugenka I'd be very surprised. On my hardware, your method takes 7 ns to execute and BitConverter.ToInt64 takes 3 ns. BitConverter.ToInt64 uses unsafe context (so no bound-check) and loop unrolling, there's no way your version is going to be faster Commented Oct 6, 2019 at 18:45

1 Answer 1

1

Bitwise operators can't be used on generic type parameters.

Even this simple cast does not compile:

result = (T)b;

But we can write this that compiles (usefull for other case):

result = (T)Convert.ChangeType(b, typeof(T));

So this does not compile:

result |= ( (T)Convert.ChangeType(b, typeof(T)) ) << pos;
Sign up to request clarification or add additional context in comments.

6 Comments

If I use ((int)b) << pos it works, so why would ((T)b) << pos not work when T is of type int?
T (generic type parameter) can be any type. We can only operate on integer numbers because of the architecture of the processor that uses bytes as units. Applying bitwise operators on references is not allowed as it will change the memory address of an instance of a type unless overloading these operators to act on an embedded value. Hence bitwise operators can't be used on generic type parameters that can match any reference of an instance of a type. And C# uses immutable for programmers references, not pointers. ((int)b) << pos compiles because it is a integer number value type.
Then the suggested Convert.ChangeType should not work either, should it? It gives "Operand << cannot be applied to operands of type T and int" error with it.
Indeed. Answer updated to be more clear about what I tried to say.
If I use ulong type for the bitwise operation itself and then cast the result to a desired type (which is either Int or Long in my case) as suggested, will performance suffer? Or should I better have two separate methods for Int and Long convertions? The reason I ask this is that performance is really critical. I have gigabytes of bynary 24 and 40-bit data which need to be converted to Int and Long respectively quite often.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.