Esta página foi útil?
Seus comentários sobre este conteúdo são importantes. Queremos saber sua opinião.
Comentários adicionais?
1500 caracteres restantes
Método Equals (Object)
Collapse the table of content
Expand the table of content
Este artigo foi traduzido por máquina. Coloque o ponteiro do mouse sobre as frases do artigo para ver o texto original. Mais informações.
Tradução
Original

Método Object.Equals (Object)

Verifica se o objeto especificado é igual ao objeto atual.

Namespace:  System
Assembly:  mscorlib (em mscorlib.dll)

public virtual bool Equals(
	Object obj
)

Parâmetros

obj
Tipo: System.Object
O objeto a ser comparado com o objeto atual.

Valor de retorno

Tipo: System.Boolean
true se o objeto especificado é igual ao objeto atual; caso contrário, false.

O tipo de comparação entre a instância atual e o parâmetro de obj depende se a instância atual for um tipo de referência ou um tipo de valor.

  • Se a instância atual for um tipo de referência, o método de Equals(Object) para igualdade de referência, e uma chamada ao método de Equals(Object) são equivalentes a uma chamada ao método de ReferenceEquals . A igualdade de referência significa que as variáveis de objeto que são comparados fazem referência ao mesmo objeto. O exemplo a seguir ilustra o resultado dessa comparação. Define uma classe de Person , que é um tipo de referência, e chama o construtor de classe de Person para criar uma instância dois novos objetos, person1a e person2de Person , que têm o mesmo valor. Também atribui person1a outra variável de objeto, person1b. Como a saída de exemplo mostram, person1a e person1b são iguais porque faz referência ao mesmo objeto. No entanto, person1a e person2 não forem iguais, embora tenha o mesmo valor.

    
    using System;
    
    // Define a reference type that does not override Equals.
    public class Person
    {
       private string personName;
    
       public Person(string name)
       {
          this.personName = name;
       }
    
       public override string ToString()
       {
          return this.personName;
       }
    }
    
    public class Example
    {
       public static void Main()
       {
          Person person1a = new Person("John");
          Person person1b = person1a;
          Person person2 = new Person(person1a.ToString());
    
          Console.WriteLine("Calling Equals:"); 
          Console.WriteLine("person1a and person1b: {0}", person1a.Equals(person1b));               
          Console.WriteLine("person1a and person2: {0}", person1a.Equals(person2));  
    
          Console.WriteLine("\nCasting to an Object and calling Equals:");
          Console.WriteLine("person1a and person1b: {0}", ((object) person1a).Equals((object) person1b));
          Console.WriteLine("person1a and person2: {0}", ((object) person1a).Equals((object) person2)); 
       }
    }
    // The example displays the following output:
    //       person1a and person1b: True
    //       person1a and person2: False
    //       
    //       Casting to an Object and calling Equals:
    //       person1a and person1b: True
    //       person1a and person2: False
    
    
    
  • Se a instância atual for um tipo de valor, o método de Equals(Object) para igualdade de valor. A igualdade de valor significa o seguinte:

    • Os dois objetos forem do mesmo tipo. Como mostra o exemplo a seguir, um objeto de Byte que tem um valor de 12 não é igual a um objeto de Int32 que tem um valor de 12, pois os dois objetos tiverem tipos diferentes de tempo de execução.

      
      using System;
      
      public class Example
      {
         public static void Main()
         {
            byte value1 = 12;
            int value2 = 12;
      
            object object1 = value1;
            object object2 = value2;
      
            Console.WriteLine("{0} ({1}) = {2} ({3}): {4}",
                              object1, object1.GetType().Name,
                              object2, object2.GetType().Name,
                              object1.Equals(object2));
         }
      }
      // The example displays the following output:
      //        12 (Byte) = 12 (Int32): False
      
      
      
    • Os valores dos campos públicos e privados dos dois objetos forem iguais. O exemplo a seguir testa a igualdade de valor. Define uma estrutura de Person , que é um tipo de valor, e chama o construtor de classe de Person para criar uma instância dois novos objetos, person1 e person2de Person , que têm o mesmo valor. Como a saída mostra o exemplo, embora as duas variáveis de objeto se refere a objetos diferentes, person1 e person2 são iguais porque têm o mesmo valor para o campo privado de personName .

      
      using System;
      
      // Define a value type that does not override Equals.
      public struct Person
      {
         private string personName;
      
         public Person(string name)
         {
            this.personName = name;
         }
      
         public override string ToString()
         {
            return this.personName;
         }
      }
      
      public struct Example
      {
         public static void Main()
         {
            Person person1 = new Person("John");
            Person person2 = new Person("John");
      
            Console.WriteLine("Calling Equals:"); 
            Console.WriteLine(person1.Equals(person2)); 
      
            Console.WriteLine("\nCasting to an Object and calling Equals:");
            Console.WriteLine(((object) person1).Equals((object) person2));  
         }
      }
      // The example displays the following output:
      //       Calling Equals:
      //       True
      //       
      //       Casting to an Object and calling Equals:
      //       True
      
      
      

Como a classe de Object é a classe base para qualquer no.NET Framework, o método de Object.Equals(Object) fornece a comparação de igualdade padrão para todos os outros tipos. Porém, os tipos de substituição que frequência o método de Equals para implementar a igualdade de valor. Para obter mais informações, consulte as notas para chamadores e notas para seções de Inheritors.

Observações para o Tempo de Execução do Windows

Quando você chama a sobrecarga do método de Equals(Object) em uma classe em Tempo de Execução do Windows, fornece o comportamento padrão para classes que não substitui Equals(Object). Ele faz parte do suporte que o .NET Framework dá para o Tempo de Execução do Windows (consulte Suporte do .NET Framework para aplicativos da Windows Store e Tempo de Execução do Windows). As classes em Tempo de Execução do Windows não herdam Object, e não no momento implementam um método de Equals(Object) . No entanto, parecem ter ToString, Equals(Object), e os métodos de GetHashCode quando devem ser usados em seu código C# ou Visual Basic, e o.NET Framework fornece o comportamento padrão para esses métodos.

ObservaçãoObservação

as classes deTempo de Execução do Windows que são gravadas em C# ou no Visual Basic podem substituir a sobrecarga do método de Equals(Object) .

Observações para chamadores

As classes derivadas substituem que frequência o método de Object.Equals(Object) para implementar a igualdade de valor. Além disso, os tipos também fornecem geralmente uma sobrecarga adicional com rigidez de tipos para o método de Equals , normalmente implementando a interface de IEquatable<T> . Quando você chama o método de Equals para testar a igualdade, você deve saber se a instância atual substitui Object.Equals e entender como uma chamada para um método específico de Equals for resolvido. Se não, você pode executar um teste para igualdade que é diferente do que você pretendeu, e o método pode retornar um valor inesperado.

O exemplo a seguir fornece uma ilustração. Cria uma instância três objetos de StringBuilder com cadeias de caracteres idênticas, e depois fazer quatro chamadas para os métodos de Equals . A primeira chamada do método retorna true, e três falsede retorno restantes.


using System;
using System.Text;

public class Example
{
   public static void Main()
   {
      StringBuilder sb1 = new StringBuilder("building a string...");
      StringBuilder sb2 = new StringBuilder("building a string...");

      Console.WriteLine("sb1.Equals(sb2): {0}", sb1.Equals(sb2));
      Console.WriteLine("((Object) sb1).Equals(sb2): {0}", 
                        ((Object) sb1).Equals(sb2));
      Console.WriteLine("Object.Equals(sb1, sb2): {0}",
                        Object.Equals(sb1, sb2));      

      Object sb3 = new StringBuilder("building a string...");
      Console.WriteLine("\nsb3.Equals(sb2): {0}", sb3.Equals(sb2));                              
   }
}
// The example displays the following output:
//       sb1.Equals(sb2): True
//       ((Object) sb1).Equals(sb2): False
//       Object.Equals(sb1, sb2): False
//
//       sb3.Equals(sb2): False


No primeiro caso, a sobrecarga com rigidez do método de StringBuilder.Equals(StringBuilder) , que testa a igualdade de valor, é chamada. Como as cadeias de caracteres atribuídas aos dois objetos de StringBuilder forem iguais, o método retornará true. No entanto, StringBuilder não substitui Object.Equals(Object). Devido a isso, quando o objeto de StringBuilder é convertido em Object, quando uma instância de StringBuilder é atribuída a uma variável do tipo Object, e quando o método de Object.Equals(Object, Object) é passado dois objetos de StringBuilder , o método de Object.Equals(Object) de opção é chamado. Como StringBuilder é um tipo de referência, equivalente ao passar os dois objetos de StringBuilder ao método de ReferenceEquals . Embora todos os três objetos de StringBuilder contêm cadeias de caracteres idênticas, se referem a três objetos distintos. No resultado, estas chamadas de três métodos retornam false.

Você pode comparar o objeto atual com outro objeto para a igualdade de referência chamando o método de ReferenceEquals . No Visual Basic, você também pode usar a palavra-chave de is (por exemplo, If Me Is otherObject Then ...).

Observações para herdeiros

Quando você define seu próprio tipo, esse tipo herda a funcionalidade definida pelo método de Equals de seu tipo base. A tabela a seguir lista a implementação padrão do método de Equals para as categorias principais do tipo no.NET Framework.

Categoria de tipo

Igualdade definida pelo

Comments

Classe derivada diretamente de Object

Object.Equals(Object)

Igualdade de referência; equivalente à chamada Object.ReferenceEquals.

Estrutura

ValueType.Equals

Igualdade de valor; direta comparação byte a byte ou comparação de campo por campo usando a reflexão.

Enumeração

Enum.Equals

Os valores devem ter o mesmo tipo de enumeração e o mesmo valor subjacente.

delegate

MulticastDelegate.Equals

O delega devem ter o mesmo tipo com listas idênticas de invocação.

Interface

Object.Equals(Object)

Igualdade de referência.

Para um tipo de valor, você sempre deve substituir Equals, porque os testa a igualdade que dependem de um baixo desempenho em ofertas de reflexão. Você também pode substituir a implementação padrão de Equals para tipos de referência para testar a igualdade de valor em vez de igualdade de referência e definir o significado preciso de igualdade de valor. Tais implementações de retorno true de Equals se os dois objetos tiverem o mesmo valor, mesmo que não são da mesma instância. O implementador de tipo decide o que constitui o valor de um objeto, mas é geralmente alguns ou todos os dados armazenados em variáveis de instância do objeto. Por exemplo, o valor de um objeto de String é baseado em caracteres da cadeia de caracteres; o método de String.Equals(Object) substitui o método de Object.Equals(Object) para retornar true para todas as duas instâncias da cadeia de caracteres que contêm os mesmos caracteres na mesma ordem.

O exemplo a seguir mostra como substituir o método de Object.Equals(Object) para testar a igualdade de valor. Substitui o método de Equals para a classe de Person . Se Person aceitou a sua implementação da classe base de igualdade, dois objetos de Person serão iguais apenas se não nulas referenciadas um único objeto. Porém, neste caso, dois objetos de Person são iguais se tiverem o mesmo valor da propriedade de Person.Id .


public class Person
{
   private string idNumber;
   private string personName;

   public Person(string name, string id)
   {
      this.personName = name;
      this.idNumber = id;
   }

   public override bool Equals(Object obj)
   {
      Person personObj = obj as Person; 
      if (personObj == null)
         return false;
      else
         return idNumber.Equals(personObj.idNumber);
   }

   public override int GetHashCode()
   {
      return this.idNumber.GetHashCode(); 
   }
}

public class Example
{
   public static void Main()
   {
      Person p1 = new Person("John", "63412895");
      Person p2 = new Person("Jack", "63412895");
      Console.WriteLine(p1.Equals(p2));
      Console.WriteLine(Object.Equals(p1, p2));
   }
}
// The example displays the following output:
//       True
//       True


Além de substituir Equals, você pode implementar a interface de IEquatable<T> para fornecer um teste com rigidez para fins de igualdade.

As instruções a seguir devem ser verdadeiras para todas as implementações do método de Equals(Object) . Na lista, x, y, e z representam as referências de objeto que não são zero.

  • x.Equals(x) retorna true, exceto nos casos que envolvem tipos de ponto flutuante. Consulte o 60559:2011 de ISO/IEC/IEEE, tecnologia da informação -- Sistemas do microprocessador -- Aritmética de ponto flutuante.

  • x.Equals(y) retorna o mesmo valor que y.Equals(x).

  • x.Equals(y) retorna true se x e y são NaN.

  • Se (x.Equals(y) && y.Equals(z)) retorna true, então x.Equals(z) retorna true.

  • As chamadas sucessivas a x.Equals(y) retornam o mesmo valor como os objetos referenciados por x e por y não são alterados.

  • x.Equals(null) retorna false.

As implementações de Equals não deve lançar exceções; sempre devem retornar um valor. Por exemplo, se obj é null, o método de Equals deve retornar false em vez de gerar ArgumentNullException.

Siga essas diretrizes ao substituir Equals(Object):

  • Tipos que a ferramenta IComparable deve substituir Equals(Object).

  • Tipos que a substituição Equals(Object) também deve substituir GetHashCode; caso contrário, as tabelas de hash podem não funcionar corretamente.

  • Você deve considerar implementar a interface de IEquatable<T> para dar suporte aos testes fortemente tipados para fins de igualdade. Sua implementação de IEquatable<T>.Equals deve retornar os resultados consistentes com Equals.

  • Se a linguagem de programação da suporte ao sobrecarregamento de operador e você sobrecarregar o operador de igualdade para um determinado tipo, você também deve substituir o método de Equals(Object) para retornar o mesmo resultado que o operador de igualdade. Isso ajuda a assegurar que a classe o código de biblioteca que que usa Equals (como ArrayList e Hashtable) se comporta que é consistente com a forma como o operador de igualdade será usada de forma pelo código de aplicativo.

bsc2ak47.collapse_all(pt-br,VS.110).gifDiretrizes para tipos de referência

As seguintes diretrizes aplicam-se ao substituir Equals(Object) para um tipo de referência:

  • Substitua Equals se a semântica de tipo são baseadas no fato de que o tipo representa alguns valores.

  • A maioria dos tipos de referência não devem sobrecarregar o operador de igualdade, mesmo se substituem Equals. No entanto, se você estiver implementando um tipo de referência destinado ter as semânticas do valor, como um tipo de número complexo, você deve substituir o operador de igualdade.

  • Você não deve substituir Equals em um tipo mutável de referência. Isso é porque substituir Equals requer que você também substitui o método de GetHashCode , como descrito na seção anterior. Isso significa que o código hash de uma instância de um tipo mutável de referência pode ser alterado durante o tempo de vida, o que pode causar o objeto a ser perdido em uma tabela de hash.

bsc2ak47.collapse_all(pt-br,VS.110).gifDiretrizes para tipos de valor

As seguintes diretrizes aplicam-se ao substituir Equals(Object) para um tipo de valor:

  • Se você estiver definindo um tipo de valor que contém um ou mais campos cujos valores são tipos de referência, você deve substituir Equals(Object). A implementação de Equals(Object) fornecida por ValueType executa uma comparação byte a byte para os tipos de valores cujos campos são todos os tipos de valor, mas usa a reflexão para executar uma comparação de campo por campo dos tipos de valores cujos campos incluem tipos de referência.

  • Se você substituir Equals e o idioma de desenvolvimento da suporte ao sobrecarregamento de operador, você deverá sobrecarregar o operador de igualdade.

  • Você deve implementar a interface de IEquatable<T> . Chame o método com rigidez de IEquatable<T>.Equals evita caso o argumento de obj .

O exemplo a seguir mostra uma classe de Point que substitui o método de Equals para fornecer a igualdade de valor, e uma classe de Point3D que seja derivada de Point. Como Point substitui Object.Equals(Object) para testar a igualdade de valor, o método de Object.Equals(Object) não é chamado. No entanto, Point3D.Equals chama Point.Equals porque Point implementa Object.Equals(Object) de um modo que fornece a igualdade de valor.


using System;

class Point
{
   protected int x, y;

   public Point() : this(0, 0) 
   { }

   public Point(int x, int y) 
   {
      this.x = x;
      this.y = y;
   }

   public override bool Equals(Object obj) 
   {
      //Check for null and compare run-time types.
      if ((obj == null) || ! this.GetType().Equals(obj.GetType())) {
         return false;
      }
      else { 
         Point p = (Point) obj; 
         return (x == p.x) && (y == p.y);
      }   
   }

   public override int GetHashCode() 
   {
      return (x << 2) ^ y;
   }

    public override string ToString()
    {
        return String.Format("Point({0}, {1})", x, y);
    }
}

sealed class Point3D: Point 
{
   int z;

   public Point3D(int x, int y, int z) : base(x, y) 
   {
      this.z = z; 
   }

   public override bool Equals(Object obj) 
   {
      Point3D pt3 = obj as Point3D;
      if (pt3 == null)
         return false;
      else
         return base.Equals((Point)obj) && z == pt3.z;
   }

   public override int GetHashCode() 
   {
      return (base.GetHashCode() << 2) ^ z;
   }

   public override String ToString() 
   {
        return String.Format("Point({0}, {1}, {2})", x, y, z);
    }
}

class Example 
{
  public static void Main() 
  {
     Point point2D = new Point(5, 5);
     Point3D point3Da = new Point3D(5, 5, 2);
     Point3D point3Db = new Point3D(5, 5, 2);
     Point3D point3Dc = new Point3D(5, 5, -1);

     Console.WriteLine("{0} = {1}: {2}", 
                       point2D, point3Da, point2D.Equals(point3Da));
     Console.WriteLine("{0} = {1}: {2}", 
                       point2D, point3Db, point2D.Equals(point3Db));        
     Console.WriteLine("{0} = {1}: {2}", 
                       point3Da, point3Db, point3Da.Equals(point3Db));
     Console.WriteLine("{0} = {1}: {2}", 
                       point3Da, point3Dc, point3Da.Equals(point3Dc));
  } 
}
// The example displays the following output:
//       Point(5, 5) = Point(5, 5, 2): False
//       Point(5, 5) = Point(5, 5, 2): False
//       Point(5, 5, 2) = Point(5, 5, 2): True
//       Point(5, 5, 2) = Point(5, 5, -1): False


O método de Point.Equals verifica para ter certeza de que o argumento de obj não é zero e que referencia uma instância do mesmo tipo do objeto. Se qualquer verificação falhará, o método retornará false.

O método de Point.Equals chama o método de GetType para determinar se os tipos de tempo de execução dos dois objetos forem idênticos. Se o método usou uma verificação do formulário obj is Point em C# ou de TryCast(obj, Point) no Visual Basic, a verificação retornaria true nos casos em que obj é uma instância de uma classe derivada de Point, mesmo que obj e a instância atual não sejam do mesmo tipo de tempo de execução. Verificando que ambos os objetos têm o mesmo tipo, o método converte obj para digitar Point e retorna o resultado da comparação dos campos de instância de dois objetos.

Em Point3D.Equals, o método herdado de Point.Equals , que substitui Object.Equals(Object), é invocado antes que qualquer outro item seja feito. Como Point3D é uma classe selada (NotInheritable no Visual Basic), verifique no formulário obj is Point em C# ou TryCast(obj, Point) no Visual Basic é suficiente para garantir que obj é um objeto de Point3D . Se for um objeto de Point3D , é convertido em um objeto de Point e passados para a implementação da classe base de Equals. Somente quando o método herdado de Point.Equals retorna true faz o método compara os campos de instância de z introduzidos na classe derivada.

O exemplo a seguir define uma classe de Rectangle que implementa internamente um retângulo como dois objetos de Point . A classe de Rectangle também substitui Object.Equals(Object) para prever a igualdade de valor.


using System;

class Rectangle 
{
   private Point a, b;

   public Rectangle(int upLeftX, int upLeftY, int downRightX, int downRightY) {
      this.a = new Point(upLeftX, upLeftY);
      this.b = new Point(downRightX, downRightY);
   }

   public override bool Equals(Object obj) {
      // Perform an equality check on two rectangles (Point object pairs).
      if (obj == null || GetType() != obj.GetType()) 
          return false;
      Rectangle r = (Rectangle)obj;
      return a.Equals(r.a) && b.Equals(r.b);
   }

   public override int GetHashCode() {
      return Tuple.Create(a, b).GetHashCode();
   }

    public override String ToString() 
    {
       return String.Format("Rectangle({0}, {1}, {2}, {3})",
                            a.x, a.y, b.x, b.y); 
    }
}

class Point 
{
  internal int x;
  internal int y;

  public Point(int X, int Y) {
     this.x = X;
     this.y = Y;
  }

  public override bool Equals (Object obj) {
     // Performs an equality check on two points (integer pairs).
     if (obj == null || GetType() != obj.GetType()) return false;
     Point p = (Point)obj;
     return (x == p.x) && (y == p.y);
  }

  public override int GetHashCode() {
     return Tuple.Create(x, y).GetHashCode();
  }
}

class Example 
{
   public static void Main() 
   {
      Rectangle r1 = new Rectangle(0, 0, 100, 200);
      Rectangle r2 = new Rectangle(0, 0, 100, 200);
      Rectangle r3 = new Rectangle(0, 0, 150, 200);

      Console.WriteLine("{0} = {1}: {2}", r1, r2, r1.Equals(r2));
      Console.WriteLine("{0} = {1}: {2}", r1, r3, r1.Equals(r3));
      Console.WriteLine("{0} = {1}: {2}", r2, r3, r2.Equals(r3));
   }
}
// The example displays the following output:
//    Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 100, 200): True
//    Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False
//    Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False


Alguns idiomas como C# e Visual Basic dão suporte ao sobrecarregamento de operador. Quando um tipo sobrecarregar o operador de igualdade, também deve substituir o método de Equals(Object) para fornecer a mesma funcionalidade. Isso é feito normalmente gravando o método de Equals(Object) em termos do operador de igualdade sobrecarregado, como no exemplo a seguir.


using System;

public struct Complex {
   public double re, im;

   public override bool Equals(Object obj) {
      return obj is Complex && this == (Complex)obj;
   }

   public override int GetHashCode() {
      return Tuple.Create(re, im).GetHashCode();
   }

   public static bool operator ==(Complex x, Complex y) {
      return x.re == y.re && x.im == y.im;
   }

   public static bool operator !=(Complex x, Complex y) {
      return !(x == y);
   }

    public override String ToString()
    {
       return String.Format("({0}, {1})", re, im);
    } 
}

class MyClass 
{
  public static void Main() 
  {
    Complex cmplx1, cmplx2;

    cmplx1.re = 4.0;
    cmplx1.im = 1.0;

    cmplx2.re = 2.0;
    cmplx2.im = 1.0;

    Console.WriteLine("{0} <> {1}: {2}", cmplx1, cmplx2, cmplx1 != cmplx2);        
    Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1.Equals(cmplx2));        

    cmplx2.re = 4.0;

    Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1 == cmplx2);        
    Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1.Equals(cmplx2));          
  }
}
// The example displays the following output:
//       (4, 1) <> (2, 1): True
//       (4, 1) = (2, 1): False
//       (4, 1) = (4, 1): True
//       (4, 1) = (4, 1): True


Como Complex é um tipo de valor, não pode ser derivado. Consequentemente, a substituição pelo método de Equals(Object) não precisa chamar GetType para determinar o tipo preciso de tempo de execução de cada objeto, mas pode usar o operador de is em C# ou o operador de TypeOf no Visual Basic para verificar o tipo do parâmetro de obj .

.NET Framework

Com suporte em: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Com suporte em: 4, 3.5 SP1

Biblioteca de Classes Portátil

Com suporte em: Biblioteca de Classes Portátil

.NET para aplicativos da Windows Store

Com suporte em: Windows 8

.NET para aplicativos do Windows Phone

Com suporte em: Windows Phone 8, Silverlight 8.1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Função Server Core sem suporte), Windows Server 2008 R2 (Função Server Core com suporte com o SP1 ou posterior, Itanium sem suporte)

O .NET Framework não oferece suporte a todas as versões de cada plataforma. Para obter uma lista das versões com suporte, consulte Requisitos do sistema do .NET Framework.

Contribuições da comunidade

ADICIONAR
Mostrar:
© 2015 Microsoft