¿Cuándo deben usarse "SqlDbType" y "size" al agregar los parámetros de SqlCommand?

Hay una pregunta relacionada con esto:

¿Cuál es el mejor método para pasar parámetros a SQLCommand?

Pero quiero saber cuáles son las diferencias y si hay algún problema con las diferentes formas.

Usualmente uso una estructura como esta:

using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(SQL, conn))
{
     cmd.CommandType = CommandType.Text;
     cmd.CommandTimeout = Settings.Default.reportTimeout;
     cmd.Parameters.Add("type", SqlDbType.VarChar, 4).Value = type;

     cmd.Connection.Open();

     using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
     {
         adapter.Fill(ds);
     }
      //use data                    
}

Ahora hay varias formas de agregar los parámetros de cmd y me pregunto cuál es el mejor:

cmd.Parameters.Add("@Name", SqlDbType.VarChar, 20).Value = "Bob";
cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Bob";
cmd.Parameters.Add("@Name").Value = "Bob";
cmd.Parameters.AddWithValue("@Name", "Bob");

Supongo que tener la longitud del campo al pasar los varchars no es preferible ya que es un valor mágico que puede cambiarse más tarde en la base de datos. ¿Es esto correcto? ¿Causa algún problema pasar un varchar de esta manera (rendimiento u otro), supongo que por defecto es varchar (max) o el equivalente de la base de datos. Estoy razonablemente feliz de que esto funcione.

La parte que más me preocupa es la pérdida de la enumeración SqlDbType si estoy usando la tercera o cuarta opción que mencioné anteriormente, no estoy proporcionando un tipo en absoluto. ¿Hay casos en los que esto no funcionará? Me imagino que los problemas con varchar se emiten incorrectamente a char o viceversa o tal vez problemas con decimal a dinero ...

En términos de la base de datos, el tipo de campo que diría es mucho menos probable que cambie que la longitud, ¿vale la pena conservarlo?

Respuestas a la pregunta(2)

Su respuesta a la pregunta