Results 1 to 9 of 9

Thread: [RESOLVED] Generic Method with BitConverter.GetBytes problem

  1. #1

    Thread Starter
    New Member
    Join Date
    Oct 2019
    Posts
    7

    Resolved [RESOLVED] Generic Method with BitConverter.GetBytes problem

    I have a simple generic method.

    Code:
     private static byte[] GetBytes<T> (T valu) 
            {
                var bytes = BitConverter.GetBytes(valu);
                if (BitConverter.IsLittleEndian)
                    Array.Reverse(bytes);
                return bytes;
            }
    The idea is that I can use this method with either a ushort or uint for T.
    But I get the following error.

    Error CS1503 Argument 1: cannot convert from 'T' to 'bool'

    The error I believe is generated because one of the overloads for BitConverter.GetBytes is bool .

    I just do not have a clue on how to resolve this, other than write my own method to convert a unit or ushort to bytes. Any suggestions or hints appreciated.

  2. #2
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    107,648

    Re: Generic Method with BitConverter.GetBytes problem

    The problem is that, in a generic method, the type T can be absolutely anything. Inside the method, you are passing the parameter of type T to GetBytes so T has to be some type that GetBytes accepts or it must be convertible to some type that GetBytes accepts. You cannot make that guarantee so that method is invalid. The reason that it mentions type bool is that that is the type of the parameter in the first overload of GetBytes. I can't test right now but you may be able to add a constraint for T as IConvertible and have it work, but I'm not 100% sure. That constraint would mean that you couldn't pass any value to that method that didn't implement IConvertible, but it doesn't sound like you want to do that anyway. If you did then that would be a problem in itself.
    csharp Code:
    1. private static byte[] GetBytes<T> (T valu) where T : IConvertible
    The problem with that is that the method may actually convert the value to a bool regardless of whether it is some other type that GetBytes would accept. The compiler won't know anything about what is going to be passed in other than it is IConvertible, so it might just convert it, even if it doesn't need to. There is no base type that only all numeric types inherit and there is no interface that only all numeric types implement so there is no way to constrain a generic type parameter to just numeric types, as convenient as that might be.

  3. #3

    Thread Starter
    New Member
    Join Date
    Oct 2019
    Posts
    7

    Re: Generic Method with BitConverter.GetBytes problem

    jmcilhinney, I appreciate you taking the time to explain what has gone wrong with my code and offering a possible solution.
    I will take another look at the code with your suggestion.

    Thanks

  4. #4
    Frenzied Member KGComputers's Avatar
    Join Date
    Dec 2005
    Location
    Cebu, PH
    Posts
    1,990

    Re: Generic Method with BitConverter.GetBytes problem

    A solution would be to explicitly check the type of T being passed to the function and execute the GetBytes() function for valid types. Other types are disregarded.

    Code:
    private static byte[] GetBytes<T>(T value) 
          {
             byte[] bytes;
             ushort val1;
             uint val2;
             Type t = typeof(T);
    
             if (t == typeof(ushort))
             {
                val1 = Convert.ToUInt16(value);
                bytes = BitConverter.GetBytes(val1);            
             }
             else if (t == typeof(uint))
             {
                val2 = Convert.ToUInt32(value);
                bytes = BitConverter.GetBytes(val2);
             }
             else
             {
                bytes = null;
             }
    
             if (BitConverter.IsLittleEndian && bytes != null)
                Array.Reverse(bytes);
    
             return bytes;
          }
    - kgc
    CodeBank: VB.NET & C#.NET | ASP.NET
    Programming: C# | VB.NET
    Blogs: Personal | Programming
    Projects: GitHub | jsFiddle
    ___________________________________________________________________________________

    Rating someone's post is a way of saying Thanks...

  5. #5

    Thread Starter
    New Member
    Join Date
    Oct 2019
    Posts
    7

    Re: Generic Method with BitConverter.GetBytes problem

    Thanks KGC for that. I was halfway there to a similar solution when you posted this.
    C# is a hobby for me and this is definitely a learning experience.

    I appreciate everyones help.

  6. #6
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    107,648

    Re: Generic Method with BitConverter.GetBytes problem

    Quote Originally Posted by KGComputers View Post
    A solution would be to explicitly check the type of T being passed to the function and execute the GetBytes() function for valid types. Other types are disregarded.

    Code:
    private static byte[] GetBytes<T>(T value) 
          {
             byte[] bytes;
             ushort val1;
             uint val2;
             Type t = typeof(T);
    
             if (t == typeof(ushort))
             {
                val1 = Convert.ToUInt16(value);
                bytes = BitConverter.GetBytes(val1);            
             }
             else if (t == typeof(uint))
             {
                val2 = Convert.ToUInt32(value);
                bytes = BitConverter.GetBytes(val2);
             }
             else
             {
                bytes = null;
             }
    
             if (BitConverter.IsLittleEndian && bytes != null)
                Array.Reverse(bytes);
    
             return bytes;
          }
    - kgc
    That's a dodgy solution and isn't even really a solution at all. It really defeats the purpose of generics. To be frank, this whole situation is one where generics should not be in the conversation. If the intention is to be able to convert ushort and uint values then just overload the method for those two types. The code will be simpler and then there's no chance of calling the method and passing something other than the two types it is intended for.

  7. #7

    Thread Starter
    New Member
    Join Date
    Oct 2019
    Posts
    7

    Re: Generic Method with BitConverter.GetBytes problem

    Quote Originally Posted by jmcilhinney View Post
    That's a dodgy solution and isn't even really a solution at all. It really defeats the purpose of generics. To be frank, this whole situation is one where generics should not be in the conversation. If the intention is to be able to convert ushort and uint values then just overload the method for those two types. The code will be simpler and then there's no chance of calling the method and passing something other than the two types it is intended for.
    This place is full of great people with great advice.
    Still confused but plenty of thing to think about.

  8. #8
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    107,648

    Re: [RESOLVED] Generic Method with BitConverter.GetBytes problem

    The whole point of generics is that they are generic, i.e. the same code works for many - possibly all - different types. Think about the List<T> class. There's no code inside that class that checks what type T is and then does something different based on that. It all just works the same no matter the type. The code provided in post #4 will work insofar as it uses a generic type parameter but it defeats the purpose of generics. It only works for two types and you have to actually look for those types specifically within the code. There's a reason that BitConverter.GetBytes is overloaded rather than generic. You should take your cue from that. You can, of course, pull out the common code to avoid violating DRY:
    csharp Code:
    1. private static byte[] GetBytes (ushort value)
    2. {
    3.     return OrderBytesForEndianness(BitConverter.GetBytes(value));
    4. }
    5.  
    6. private static byte[] GetBytes (uint value)
    7. {
    8.     return OrderBytesForEndianness(BitConverter.GetBytes(value));
    9. }
    10.  
    11. private static byte[] OrderBytesForEndianness (byte[] bytes)
    12. {
    13.     if (BitConverter.IsLittleEndian)
    14.         Array.Reverse(bytes);
    15.  
    16.     return bytes;
    17. }

  9. #9
    Frenzied Member KGComputers's Avatar
    Join Date
    Dec 2005
    Location
    Cebu, PH
    Posts
    1,990

    Re: [RESOLVED] Generic Method with BitConverter.GetBytes problem

    Quote Originally Posted by jmcilhinney View Post
    The whole point of generics is that they are generic, i.e. the same code works for many - possibly all - different types. Think about the List<T> class. There's no code inside that class that checks what type T is and then does something different based on that. It all just works the same no matter the type. The code provided in post #4 will work insofar as it uses a generic type parameter but it defeats the purpose of generics. It only works for two types and you have to actually look for those types specifically within the code. There's a reason that BitConverter.GetBytes is overloaded rather than generic. You should take your cue from that. You can, of course, pull out the common code to avoid violating DRY:
    csharp Code:
    1. private static byte[] GetBytes (ushort value)
    2. {
    3.     return OrderBytesForEndianness(BitConverter.GetBytes(value));
    4. }
    5.  
    6. private static byte[] GetBytes (uint value)
    7. {
    8.     return OrderBytesForEndianness(BitConverter.GetBytes(value));
    9. }
    10.  
    11. private static byte[] OrderBytesForEndianness (byte[] bytes)
    12. {
    13.     if (BitConverter.IsLittleEndian)
    14.         Array.Reverse(bytes);
    15.  
    16.     return bytes;
    17. }
    * Indeed, the generic approach isn't necessary and perhaps an overkill. Wherein you can simply overload the function with the required types as shown in your solution.

    JMC, after researching, I found out that Generic constraints for numeric types isn't supported yet. But several workarounds were presented and one of them is using Policies which is close to a constraint.
    https://stackoverflow.com/questions/...-numeric-types Will this satisfy a generic approach? Your thoughts.

    Another option that I found is to assign the valu in post#1 to a dynamic variable and pass the dynamic variable to the BitConverter.GetBytes() instead of the valu variable. (Note: this will generate a runtime error if a string variable is passed to the GetBytes() function. You may put the GetBytes() in a try/catch function and handle the exception from there.)

    - kgc
    Last edited by KGComputers; Aug 27th, 2021 at 04:52 AM.
    CodeBank: VB.NET & C#.NET | ASP.NET
    Programming: C# | VB.NET
    Blogs: Personal | Programming
    Projects: GitHub | jsFiddle
    ___________________________________________________________________________________

    Rating someone's post is a way of saying Thanks...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width