| File: Classification\DataClassificationSet.cs | Web Access |
| Project: src\src\Libraries\Microsoft.Extensions.Compliance.Abstractions\Microsoft.Extensions.Compliance.Abstractions.csproj (Microsoft.Extensions.Compliance.Abstractions) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Linq; using Microsoft.Shared.Diagnostics; using Microsoft.Shared.Pools; namespace Microsoft.Extensions.Compliance.Classification; /// <summary> /// Represents a set of data classifications. /// </summary> public sealed class DataClassificationSet : IEquatable<DataClassificationSet> { private readonly HashSet<DataClassification> _classifications = []; private readonly int _cachedHashCode; /// <summary> /// Initializes a new instance of the <see cref="DataClassificationSet"/> class. /// </summary> /// <param name="classification">The class to include in the set.</param> public DataClassificationSet(DataClassification classification) { _ = _classifications.Add(classification); _cachedHashCode = ComputeHashCode(); } /// <summary> /// Initializes a new instance of the <see cref="DataClassificationSet"/> class. /// </summary> /// <param name="classifications">The classes to include in the set.</param> public DataClassificationSet(IEnumerable<DataClassification> classifications) { _ = Throw.IfNull(classifications); _classifications.UnionWith(classifications); _cachedHashCode = ComputeHashCode(); } /// <summary> /// Initializes a new instance of the <see cref="DataClassificationSet"/> class. /// </summary> /// <param name="classifications">The classes to include in the set.</param> public DataClassificationSet(params DataClassification[] classifications) { _ = Throw.IfNull(classifications); _classifications.UnionWith(classifications); _cachedHashCode = ComputeHashCode(); } /// <summary> /// Converts a single classification to a data classification set. /// </summary> /// <param name="classification">The classification to include in the set.</param> public static implicit operator DataClassificationSet(DataClassification classification) { return FromDataClassification(classification); } /// <summary> /// Converts a single classification to a data classification set. /// </summary> /// <param name="classification">The classification to include in the set.</param> /// <returns>The resulting data classification set.</returns> public static DataClassificationSet FromDataClassification(DataClassification classification) => new(classification); /// <summary> /// Creates a new data classification set that combines the current classifications with another set. /// </summary> /// <param name="other">The other set.</param> /// <remarks> /// This method doesn't modify the two input sets, it creates a new set. /// </remarks> /// <returns>The resulting set which combines the current instance's classifications and the other ones.</returns> public DataClassificationSet Union(DataClassificationSet other) { _ = Throw.IfNull(other); var combinedClassifications = new HashSet<DataClassification>(_classifications); combinedClassifications.UnionWith(other._classifications); return new DataClassificationSet(combinedClassifications); } /// <summary> /// Gets a hash code for the current object instance. /// </summary> /// <returns>The hash code value.</returns> public override int GetHashCode() => _cachedHashCode; /// <summary> /// Compares an object with the current instance to see if they contain the same classifications. /// </summary> /// <param name="obj">The other data classification to compare to.</param> /// <returns><see langword="true"/> if the two sets contain the same classifications.</returns> public override bool Equals(object? obj) => Equals(obj as DataClassificationSet); /// <summary> /// Compares an object with the current instance to see if they contain the same classifications. /// </summary> /// <param name="other">The other data classification to compare to.</param> /// <returns><see langword="true"/> if the two sets contain the same classifications.</returns> public bool Equals(DataClassificationSet? other) => other != null && _classifications.SetEquals(other._classifications); /// <summary> /// Returns a string representation of this object. /// </summary> /// <returns>The string representation of this object.</returns> public override string ToString() { var sb = PoolFactory.SharedStringBuilderPool.Get(); var a = _classifications.ToArray(); Array.Sort(a, (x, y) => { var result = string.Compare(x.TaxonomyName, y.TaxonomyName, StringComparison.Ordinal); return result != 0 ? result : string.Compare(x.Value, y.Value, StringComparison.Ordinal); }); _ = sb.Append('['); foreach (var c in a) { if (sb.Length > 1) { _ = sb.Append(','); } _ = sb.Append(c); } _ = sb.Append(']'); var result = sb.ToString(); PoolFactory.SharedStringBuilderPool.Return(sb); return result; } /// <summary> /// Computes the hash code for the current object instance. /// </summary> /// <returns>The computed hash code.</returns> private int ComputeHashCode() { #if NETFRAMEWORK int hash = 0; foreach (var item in _classifications) { hash ^= item.GetHashCode(); } return hash; #else var hash = default(HashCode); foreach (var item in _classifications) { hash.Add(item); } return hash.ToHashCode(); #endif } }