Maison >développement back-end >C++ >Comment comparer les propriétés d'un objet en C# ?

Comment comparer les propriétés d'un objet en C# ?

Patricia Arquette
Patricia Arquetteoriginal
2025-01-22 21:56:11388parcourir

How to Compare Object Properties in C#?

Une explication détaillée des propriétés des objets C#

Dans des scénarios tels que les tests unitaires ou la vérification des données, la nécessité de comparer les valeurs des propriétés des objets est très courante. C# fournit plusieurs méthodes pour réaliser cette fonctionnalité, chacune avec ses propres avantages et inconvénients.

Méthode 1 : Utiliser la réflexion

Le mécanisme de réflexion permet une inspection dynamique des propriétés des objets et une comparaison de leurs valeurs. Voici une méthode de comparaison basée sur la réflexion :

<code class="language-csharp">public bool PropertiesEqual(object comparisonObject)
{
    Type sourceType = this.GetType();
    Type destinationType = comparisonObject.GetType();

    if (sourceType == destinationType)
    {
        PropertyInfo[] sourceProperties = sourceType.GetProperties();
        foreach (PropertyInfo pi in sourceProperties)
        {
            if ((sourceType.GetProperty(pi.Name).GetValue(this, null) == null && destinationType.GetProperty(pi.Name).GetValue(comparisonObject, null) == null))
            {
                // 两个属性都为 null,无需比较
            }
            else if (!(sourceType.GetProperty(pi.Name).GetValue(this, null).ToString() == destinationType.GetProperty(pi.Name).GetValue(comparisonObject, null).ToString()))
            {
                // 只要一个属性值不同,则返回 false
                return false;
            }
        }
    }
    else
    {
        throw new ArgumentException("比较对象必须为同一类型。", "comparisonObject");
    }

    return true;
}</code>

Méthode 2 : Utiliser des génériques et LINQ

Les génériques et LINQ fournissent une méthode de comparaison plus simple :

<code class="language-csharp">public static bool PublicInstancePropertiesEqual<T>(T self, T to, params string[] ignore) where T : class
{
    if (self != null && to != null)
    {
        Type type = typeof(T);
        List<string> ignoreList = new List<string>(ignore);
        var unequalProperties =
            from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
            where !ignoreList.Contains(pi.Name) && pi.GetUnderlyingType().IsSimpleType() && pi.GetIndexParameters().Length == 0
            let selfValue = type.GetProperty(pi.Name).GetValue(self, null)
            let toValue = type.GetProperty(pi.Name).GetValue(to, null)
            where selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue))
            select selfValue;
        return !unequalProperties.Any();
    }
    return self == to;
}

public static class TypeExtensions
{
    public static bool IsSimpleType(this Type type)
    {
        return
            type.IsValueType ||
            type.IsPrimitive ||
            new[]
            {
                typeof(String),
                typeof(Decimal),
                typeof(DateTime),
                typeof(DateTimeOffset),
                typeof(TimeSpan),
                typeof(Guid)
            }.Contains(type) ||
            (Convert.GetTypeCode(type) != TypeCode.Object);
    }

    public static Type GetUnderlyingType(this MemberInfo member)
    {
        switch (member.MemberType)
        {
            case MemberTypes.Event:
                return ((EventInfo)member).EventHandlerType;
            case MemberTypes.Field:
                return ((FieldInfo)member).FieldType;
            case MemberTypes.Method:
                return ((MethodInfo)member).ReturnType;
            case MemberTypes.Property:
                return ((PropertyInfo)member).PropertyType;
            default:
                throw new ArgumentException("输入的 MemberInfo 必须是 EventInfo、FieldInfo、MethodInfo 或 PropertyInfo 类型");
        }
    }
}</code>

Remarques

  • Performance : La réflexion est moins performante que l'accès direct aux propriétés.
  • Sécurité des types : Les méthodes génériques garantissent la sécurité des types et réduisent les erreurs.
  • Extensibilité : Les méthodes d'extension facilitent l'intégration dans un autre code.
  • Limitations : Les deux méthodes ne peuvent pas gérer les propriétés contenant des objets complexes ou des références circulaires.

Résumé

La sélection de la méthode dépend des besoins spécifiques. Pour les scénarios avec des exigences de performances élevées, il est recommandé d'accéder directement aux propriétés ; pour les scénarios qui nécessitent une sécurité de type et une évolutivité, la méthode générique LINQ est plus adaptée.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn