C#中如何基于独立属性名集合检查列表多属性组合的唯一性
Hey there! Let's tackle this problem step by step. You’re right to lean on reflection here—it’s exactly the tool you need for dynamically accessing properties using string names. Here’s a practical, easy-to-follow implementation to check if your selected attribute combinations are unique across the product collection:
Step 1: Build a helper to fetch property values via reflection
First, we need a way to get the value of any property from a Product object using its string name. This helper method uses reflection to do just that, with optional caching to boost performance for large collections:
// Cache property info to avoid repeated reflection overhead (optional but recommended) private readonly Dictionary<string, PropertyInfo> _productPropertyCache = new(); private object GetPropertyValue(object obj, string propertyName) { if (!_productPropertyCache.TryGetValue(propertyName, out PropertyInfo property)) { property = obj.GetType().GetProperty(propertyName); _productPropertyCache[propertyName] = property; } return property?.GetValue(obj); }
Step 2: Generate a unique key for each attribute combination
Next, we’ll create a unique identifier for each product based on your selected attributes. You can choose between two approaches:
- Tuple/ValueTuple: Type-safe and avoids string concatenation issues
- Delimited string: Simple and works for any number of attributes
Here’s the string-based approach (great for flexibility):
private string CreateCombinationKey(Product product, List<string> selectedAttributes) { // Join property values with a unique delimiter to avoid accidental collisions return string.Join("|", selectedAttributes .Select(attr => GetPropertyValue(product, attr)?.ToString() ?? string.Empty)); }
Step 3: Implement the uniqueness check
Use a HashSet to track which attribute combinations we’ve already seen. If we encounter a key that’s already in the set, we know we have a duplicate:
private bool AreAttributeCombinationsUnique(List<Product> products, List<string> selectedAttributes) { var seenCombinations = new HashSet<string>(); foreach (Product product in products) { string combinationKey = CreateCombinationKey(product, selectedAttributes); // HashSet.Add returns false if the key already exists if (!seenCombinations.Add(combinationKey)) { return false; // Duplicate found } } return true; // All combinations are unique }
Test it with your example
Plug in your existing code to see it in action:
public class Product { public string Name { get; set; } public string Type { get; set; } public string Price { get; set; } } private List<string> selectedProductAttributes = new() { "Name", "Type" }; private List<Product> products = new() { new Product { Name= "a", Type="t1", Price="10" }, new Product { Name= "a", Type="t1", Price="20" }, new Product { Name= "b", Type="t2", Price="30" } }; // Check for unique combinations bool isUnique = AreAttributeCombinationsUnique(products, selectedProductAttributes); Console.WriteLine(isUnique); // Outputs False (since first two products share Name+Type)
Quick notes to keep in mind
- Null handling: The code uses
?? string.Emptyto handle null property values, so nulls won’t break the key generation. - Performance: The property cache helps reduce reflection overhead if you’re checking large collections multiple times.
- Type safety: If you prefer type safety over flexibility, swap the string key for a
ValueTuple(works best for a fixed number of attributes).
内容的提问来源于stack exchange,提问作者Sumit Deshpande

