Let me clarify the unchecked business. The MSDN page states that unchecked is used to prevent overflow checking, which would otherwise, when inside a checked context, give a compile error or throw an exception.
...IF inside a checked context.
The context is checked either explicitly:
checked { ... }
or implicitly*, when dealing with compile-time constants:
byte b = (byte)-6; //compile error byte b2 = (byte)(200 + 200); //compile error int i = int.MaxValue + 10; //compiler error
But when dealing with runtime variables, the context is unchecked by default**:
sbyte sb = -6; byte b = (byte)sb; //no problem, sb is a variable int i = int.MaxValue; int j = i + 10; //no problem, i is a variable
To summarize and answer the original question:
Need byte<->sbyte conversion on constants? Use unchecked and cast:
byte b = unchecked( (byte) -6 );
Need byte<->sbyte conversion on variables? Just cast:
sbyte sb = -6; byte b = (byte) sb;
* There is a third way to get a checked context by default: by tweaking the compiler settings. E.g. Visual Studio -> Project properties -> Build -> Advanced... -> [X] Check for arithmetic overflow/underflow
** The runtime context is unchecked by default in C#. In VB.NET for example, the default runtime context is CHECKED.
byte?uncheckedfor casting runtime variables. See my answer for the full details.