Difference between Object, Dynamic and var

Asked

Viewed 10,375 times

36

I’m running some tests and it seems to me Object and Dynamic perform the same task as opposed to var that once assigned it is impossible to change their type, what is the difference between them?

var variavel = 15; // É preciso atribuir um valor, se não não compila, não aceita iniciar como NULL;
object objeto = 15;
dynamic dinamico = 15;

Console.WriteLine(variavel.GetType().ToString()); // Int
Console.WriteLine(objeto.GetType().ToString()); // Int
Console.WriteLine(dinamico.GetType().ToString()); // Int

variavel = "Teste"; // Não deixa atribuir
objeto = "Teste";
dinamico = "Teste";

Console.WriteLine(variavel.GetType().ToString()); // Int
Console.WriteLine(objeto.GetType().ToString()); // String
Console.WriteLine(dinamico.GetType().ToString()); // String
Console.ReadKey();
  • I’ve given a very detailed and exhaustive answer... if you have any further questions, feel free to ask. = D

4 answers

40


Object

Refers to the type System.Object which is the basis for all other types, whether reference types or value types.

Such a variable/parameter allows associating any type of data, where if it is a class, a simple assignment occurs, and if it is a value type, the Boxing of that value occurs first, and then an assignment.

In addition, there is special treatment for nullable types (Nullable<TStruct>, in C# may be represented by TStruct?), in which, if the nullable .HasValue is false, the value is considered null, otherwise, the value contained in nullable is Boxed and then the assignment operation is made.

object x = 1; // vai ocorrer boxing do valor 1, pois Int32 é um value-type
object y = "str"; // não vai haver boxing, pois String é uma reference-type
// nullable é value-type, mas nunca será boxed dentro de um object
int? i = null;
int? j = 10;
object z1 = i; // z1 será null
object z2 = j; // z2 terá um Int32 com o valor 10 boxed e atribuido à variável

var

That’s what you call sugar-syntactic. It’s just a keyword that’s used for the compiler to guess the type when compiling. This is called type inference. I’ll be direct:

var x = 1;
var y = "str";
var z = x == 2 ? new MeuObjeto("xpto") : new MeuObject("abc");

will be translated by the compiler to:

Int32 x = 1;
String y = "str";
MeuObjeto z = x == 2 ? new MeuObjeto("xpto") : new MeuObject("abc");

When var is the only option?

There is a use where var It’s not just sugary-syntactic. The big deal in this type inference is anonymous guys, which means, types that are created inline, and that have no name:

var a = new { Nome = "Miguel" };

There is no C# translation for this. But when compiling, C# will generate a type instantly, and use it:

<Projection>f__0 a = new <Projection>f__0 { Nome = "Miguel" };

Being generated a class <Projection>f__0, perfectly valid!

Dynamic

This is a keyword that allows calling methods and properties of any object, without knowing your type. This is known as late-Binding, that is, is to associate the call to the destination method/property only at the time the call is made.

Note that when doing Dispatch, a Dispatcher will be used that acts exactly like C# (or Visual Basic if using Dynamic in VB). This Dispatcher tries to locate the method/property/operation the same way C# would... and if it fails, a except that the call cannot be made.

Find out more about Duck-Typing, because the concept is very similar... but the same.

Performance of dynamic

But don’t think you’ll miss rivers of performance by doing this, for the implementation of a call on a dynamic is very efficient. At the exact point the call is made, is compiled a call to a static object that caches the method to be called in a dictionary of types. This means that the call is only slow the first time for each type, but the second time the same code is executed with the same type, it will be much faster.

You refer to that call as call-site. Note that a line of code may contain multiple call-sites, one for each operation being done:

// existem 2 call-sites na linha abaixo:
// - uma para a propriedade Length,
// - e outro para o type-cast para int
int a = (int)dyn.Length;

dynamic is not a guy

dynamic is not a type, but yes, a keyword that determines a different way of doing Dispatch (choice of which method/property will actually be called)... to have a parallel, inheritance and polymorphism are two other ways of doing Dispatch, different from when dynamic is used.

Though I’m not a guy, there are types that are associated with the keyword dynamic. These guys are part of the DLR (Dynamic Language Runtime)

Reference:

  • 1

    Duck-Typing does not necessarily involve typing or dynamic Dispatch. In C++, in templates, the conference is done at build time and using static typing.

  • In C# there is only the Duck-Typing option with dynamic Dispatch, and the call destination is on a map, within a static field that represents each of the calls made on dynamic in the code. This was given the name of Call-Site.

  • I was referring to Duck-Typing in templates: http://en.wikipedia.org/wiki/Duck_typing#Templates_or_generic_types

11

The guy object is the parent type of all other types in .NET. This is why you can use a variable of type object to point out or store all kinds of information on .NET. For those who have doubts about why, I suggest studying two topics of object orientation: inheritance and polymorphism.

If you use the reserved word var to create a variable, it will be typed statically. The type the variable will have will be decided by the rest of the code - the compiler is responsible for determining the most appropriate type.

If you use the reserved word dynamic the behaviour is similar to that of object, but no type check is done at compile time. (source: MSDN). This means that any errors by invalid calls or assignments will not be detected before the program is built. If such errors pass beaten by the compiler, they may manifest at runtime.

The reserved word dynamic really seems to have no sense in a purely . NET world, in which you could perhaps turn off compiler warnings and errors in certain cases. But it can be useful when you integrate. NET with some other platform, or when we use C# in conjunction with dynamic typing languages such as Iron Python (this is quoted in the source I used above).

  • var is not strongly typed, like any other type in C# (a weakly typed language), thanks to polymorphism and casting. The correct is to say that var creates a statically typed variable, or typed at compile time.

  • @Mephy is right. I’ll edit, thanks for the tip.

  • 2

    @Mephy, C# would not be strongly typed instead of weakly typed ?

3

I’ll be very colloquial:

  • dynamic is an aberration that Microsoft created to suit the web world and the REST API’s, it’s like a variant type in C# that can receive an object of any type. Why freak? Because it is an unsafe type (type-unsafe) inside a link that says type-safe.
  • var is an easy to write and determines that the compiler at compile time will determine which type will be based on the first value the object received.
  • object is the nothingness and all at the same time. Basically everything derives from Object, but in the programming if vc want to use it will be necessary to test and convert in the type of object you want...

I recommend reading the basic programming books in C#, I really liked the Wrox (C# for Begginers)

  • "but in the programming if you want to use it will be necessary to test and convert in the type of object you want..." If all you want is to read the hash or the type of an object, object it is convenient and dispensation castor other forms of manipulation.

  • Yes, I agree and I think it was rare the cases where I tested the type of an object not to use it. The use of object is very common when we use only the standard functions .ToString(), .GetHashCode(), .GetType()

3

public sealed class Exemplo()
{
     private String _nome;

     public Exemplo(String nome)
     {    
          _nome = nome
     }

     public String Nome
     {
          get { return (String)_nome; }
          internal set { _nome = (Object)value; }
     }

     public String NomeInvertido
     {
          get 
          {
             var ex = new Exemplo(_nome); //Boa hora para você usar var, você sabe que new Exemplo(String) gera um objeto do tipo Exemplo. Você está dentro da própria classe.
             ex.Inverte();
             return ex.Nome;
          }
     }

     private void Inverte()
     {
          Char[] letras = _nome.ToCharArray();
          String inverso = String.Empty;
          for (Int32 i = letras.Length - 1; i > -1; i--)
               inverso += letras[i];
          _nome = inverso;
     }
}

Exemplo explicito = new Exemplo("Guilherme");
//Object exemplo = new Exemplo("Guilherme");
var implicito = new Exemplo("Guilherme");
dynamic dinamico = new Exemplo("Guilherme");

//SUCESSO:
Console.WriteLine(explicito.Nome); //Guilherme
Console.WriteLine(implicito.Nome); //Guilherme
Console.WriteLine(dinamico.Nome); //Guilherme

//Acessando um método Private
explicito.Inverte(); //Método não é público. Não pode ser acessado daqui.
implicito.Inverte(); //Método não é público. Não pode ser acessado daqui.
dinamico.Inverte(); //Não vai dar problema na hora de compilar, porem no momento que você executar esse código vai gerar uma exceção.

dinamico.Sobrenome; //Não existe esta propriedade porem só vai descobrir isso depois de executar a aplicação. Digamos que você utilize uma DLL externa, e a classe Exemplo está nessa DLL, hoje você não tem essa propriedade, mas amanhã você atualiza essa DLL e essa propriedade irá existir sem problemas...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.