CRC 16 code with "unsafe features"
Your code looks pretty good except for the static table. More about that later.

Unsafe code has a few things that can make code go faster, like pointers to arrays and arrays on the stack.

A pointer to array would make code only faster if the code is iterating through that array. ComputeChecksum does iterate trough data, so yes, this part could become a little bit faster. We are talking about microseconds.

You are also iterating through an the table array inside the constructor. So creation of this table could also become a littel bit faster.

Personally: I would not use unsafe code in your case.

About the static

You have a static table, but when you create a new instance of Crc16Ccitt it will recalculate all the (same) values. (Talking about performance loss!) If you have two instances of Crc16Ccitt with different polynomials, then one of your instances will calculate it CRC's wrong, because they both share the same table (since it is static).

How to solve this in a faster and safer way?

Use a static! (Huh?) Yes, a static but another one:

static private readonly Dictionary&lt;Crc16Mode, ushort[]&gt; _tables; This will store all calculated tables.

In your class use a local field: ushort[] _table; This one will hold the (already) calculated table. If the table was not calculated, it will be calculated and stored inside _tables.

You also use this mechanism to store hard coded calcaulated tables, as Jesse suggests. In that case you would assign your hard code table to the dictionary inside a static constructor.

Your code could become like this:

public enum Crc16Mode : ushort { Standard = 0xA001, CcittKermit = 0x8408 }

public class Crc16Ccitt
{
    #region Static members

    static private readonly Dictionary&lt;Crc16Mode, ushort[]&gt; _tables = new Dictionary&lt;Crc16Mode, ushort[]&gt;();

    static private ushort[] GetTable(Crc16Mode mode)
    {
        lock (_tables)
        {
            ushort[] table;
            if (_tables.TryGetValue(mode, out table))
                return table;

            ushort polynomial = (ushort)mode;
            for (ushort i = 0; i &lt; table.Length; ++i)
            {
                ushort value = 0;
                ushort temp = i;
                for (byte j = 0; j &lt; 8; ++j)
                {
                    if (((value ^ temp) &amp; 0x0001) != 0)
                        value = (ushort)((value &gt;&gt; 1) ^ polynomial);
                    else
                        value &gt;&gt;= 1;
                    temp &gt;&gt;= 1;
                }
                table[i] = value;
            }
            _tables[mode] = table;
            return table;
        }
    }

    #endregion

    private readonly ushort[] _table = new ushort[256];

    public Crc16Ccitt(Crc16Mode mode)
    {
        _table = GetTable(mode);
    }

    public ushort ComputeChecksum(params byte[] bytes)
    {
        ushort crc = 0;
        for (int i = 0; i &lt; bytes.Length; ++i)
        {
            byte index = (byte)(crc ^ bytes[i]);
            crc = (ushort)((crc &gt;&gt; 8) ^ _table[index]);
        }
        return crc;
    }
}