Merge remote-tracking branch 'origin/v8/dev' into netcore/feature/merge-v8-18-01-2021
# Conflicts: # .gitignore # build/NuSpecs/UmbracoCms.Core.nuspec # src/SolutionInfo.cs # src/Umbraco.Core/Configuration/UmbracoSettings/BackOfficeElement.cs # src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs # src/Umbraco.Core/Configuration/UmbracoSettings/IBackOfficeSection.cs # src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs # src/Umbraco.Core/IO/SystemFiles.cs # src/Umbraco.Core/Models/ContentBase.cs # src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs # src/Umbraco.Core/Persistence/UmbracoDatabaseExtensions.cs # src/Umbraco.Core/Runtime/CoreRuntime.cs # src/Umbraco.Core/RuntimeOptions.cs # src/Umbraco.Core/RuntimeState.cs # src/Umbraco.Core/Telemetry/TelemetryMarkerComponent.cs # src/Umbraco.Core/Telemetry/TelemetryMarkerComposer.cs # src/Umbraco.Examine/Umbraco.Examine.csproj # src/Umbraco.Infrastructure/HostedServices/ReportSiteTask.cs # src/Umbraco.Infrastructure/Install/InstallStepCollection.cs # src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs # src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs # src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs # src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs # src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/Repositories/ContentTypeRepositoryTest.cs # src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs # src/Umbraco.Tests/Runtimes/StandaloneTests.cs # src/Umbraco.Tests/Testing/TestDatabase.cs # src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs # src/Umbraco.Web.UI.Client/src/installer/steps/database.controller.js # src/Umbraco.Web.UI.NetCore/Views/Partials/Grid/Editors/TextString.cshtml # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml # src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml # src/Umbraco.Web.UI/config/umbracoSettings.Release.config # src/Umbraco.Web/Composing/CompositionExtensions/Installer.cs # src/Umbraco.Web/Editors/PreviewController.cs # src/Umbraco.Web/Editors/UsersController.cs # src/Umbraco.Web/JavaScript/PreviewInitialize.js # src/Umbraco.Web/Telemetry/TelemetryComponent.cs # src/Umbraco.Web/UmbracoApplication.cs
This commit is contained in:
@@ -98,10 +98,15 @@ namespace Umbraco.Core.Models
|
||||
set
|
||||
{
|
||||
if (_schedule != null)
|
||||
_schedule.CollectionChanged -= ScheduleCollectionChanged;
|
||||
{
|
||||
_schedule.ClearCollectionChangedEvents();
|
||||
}
|
||||
|
||||
SetPropertyValueAndDetectChanges(value, ref _schedule, nameof(ContentSchedule));
|
||||
if (_schedule != null)
|
||||
{
|
||||
_schedule.CollectionChanged += ScheduleCollectionChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,10 +228,16 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_publishInfos != null) _publishInfos.CollectionChanged -= PublishNamesCollectionChanged;
|
||||
if (_publishInfos != null)
|
||||
{
|
||||
_publishInfos.ClearCollectionChangedEvents();
|
||||
}
|
||||
|
||||
_publishInfos = value;
|
||||
if (_publishInfos != null)
|
||||
{
|
||||
_publishInfos.CollectionChanged += PublishNamesCollectionChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +332,7 @@ namespace Umbraco.Core.Models
|
||||
else
|
||||
Properties.EnsurePropertyTypes(contentType.CompositionPropertyTypes);
|
||||
|
||||
Properties.CollectionChanged -= PropertiesChanged; // be sure not to double add
|
||||
Properties.ClearCollectionChangedEvents(); // be sure not to double add
|
||||
Properties.CollectionChanged += PropertiesChanged;
|
||||
}
|
||||
|
||||
@@ -438,7 +449,7 @@ namespace Umbraco.Core.Models
|
||||
//if culture infos exist then deal with event bindings
|
||||
if (clonedContent._publishInfos != null)
|
||||
{
|
||||
clonedContent._publishInfos.CollectionChanged -= PublishNamesCollectionChanged; //clear this event handler if any
|
||||
clonedContent._publishInfos.ClearCollectionChangedEvents(); //clear this event handler if any
|
||||
clonedContent._publishInfos = (ContentCultureInfosCollection)_publishInfos.DeepClone(); //manually deep clone
|
||||
clonedContent._publishInfos.CollectionChanged += clonedContent.PublishNamesCollectionChanged; //re-assign correct event handler
|
||||
}
|
||||
@@ -446,7 +457,7 @@ namespace Umbraco.Core.Models
|
||||
//if properties exist then deal with event bindings
|
||||
if (clonedContent._schedule != null)
|
||||
{
|
||||
clonedContent._schedule.CollectionChanged -= ScheduleCollectionChanged; //clear this event handler if any
|
||||
clonedContent._schedule.ClearCollectionChangedEvents(); //clear this event handler if any
|
||||
clonedContent._schedule = (ContentScheduleCollection)_schedule.DeepClone(); //manually deep clone
|
||||
clonedContent._schedule.CollectionChanged += clonedContent.ScheduleCollectionChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
@@ -138,7 +138,11 @@ namespace Umbraco.Core.Models
|
||||
get => _properties;
|
||||
set
|
||||
{
|
||||
if (_properties != null) _properties.CollectionChanged -= PropertiesChanged;
|
||||
if (_properties != null)
|
||||
{
|
||||
_properties.ClearCollectionChangedEvents();
|
||||
}
|
||||
|
||||
_properties = value;
|
||||
_properties.CollectionChanged += PropertiesChanged;
|
||||
}
|
||||
@@ -173,10 +177,15 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_cultureInfos != null) _cultureInfos.CollectionChanged -= CultureInfosCollectionChanged;
|
||||
if (_cultureInfos != null)
|
||||
{
|
||||
_cultureInfos.ClearCollectionChangedEvents();
|
||||
}
|
||||
_cultureInfos = value;
|
||||
if (_cultureInfos != null)
|
||||
{
|
||||
_cultureInfos.CollectionChanged += CultureInfosCollectionChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +488,7 @@ namespace Umbraco.Core.Models
|
||||
//if culture infos exist then deal with event bindings
|
||||
if (clonedContent._cultureInfos != null)
|
||||
{
|
||||
clonedContent._cultureInfos.CollectionChanged -= CultureInfosCollectionChanged; //clear this event handler if any
|
||||
clonedContent._cultureInfos.ClearCollectionChangedEvents(); //clear this event handler if any
|
||||
clonedContent._cultureInfos = (ContentCultureInfosCollection)_cultureInfos.DeepClone(); //manually deep clone
|
||||
clonedContent._cultureInfos.CollectionChanged += clonedContent.CultureInfosCollectionChanged; //re-assign correct event handler
|
||||
}
|
||||
@@ -487,7 +496,7 @@ namespace Umbraco.Core.Models
|
||||
//if properties exist then deal with event bindings
|
||||
if (clonedContent._properties != null)
|
||||
{
|
||||
clonedContent._properties.CollectionChanged -= PropertiesChanged; //clear this event handler if any
|
||||
clonedContent._properties.ClearCollectionChangedEvents(); //clear this event handler if any
|
||||
clonedContent._properties = (IPropertyCollection)_properties.DeepClone(); //manually deep clone
|
||||
clonedContent._properties.CollectionChanged += clonedContent.PropertiesChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@ namespace Umbraco.Core.Models
|
||||
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Clears all <see cref="CollectionChanged"/> event handlers
|
||||
/// </summary>
|
||||
public void ClearCollectionChangedEvents() => CollectionChanged = null;
|
||||
|
||||
private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
CollectionChanged?.Invoke(this, args);
|
||||
|
||||
@@ -266,7 +266,10 @@ namespace Umbraco.Core.Models
|
||||
set
|
||||
{
|
||||
if (_noGroupPropertyTypes != null)
|
||||
_noGroupPropertyTypes.CollectionChanged -= PropertyTypesChanged;
|
||||
{
|
||||
_noGroupPropertyTypes.ClearCollectionChangedEvents();
|
||||
}
|
||||
|
||||
_noGroupPropertyTypes = new PropertyTypeCollection(SupportsPublishing, value);
|
||||
_noGroupPropertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
PropertyTypesChanged(_noGroupPropertyTypes, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
@@ -484,14 +487,14 @@ namespace Umbraco.Core.Models
|
||||
// its ignored from the auto-clone process because its return values are unions, not raw and
|
||||
// we end up with duplicates, see: http://issues.umbraco.org/issue/U4-4842
|
||||
|
||||
clonedEntity._noGroupPropertyTypes.CollectionChanged -= PropertyTypesChanged; //clear this event handler if any
|
||||
clonedEntity._noGroupPropertyTypes.ClearCollectionChangedEvents(); //clear this event handler if any
|
||||
clonedEntity._noGroupPropertyTypes = (PropertyTypeCollection) _noGroupPropertyTypes.DeepClone(); //manually deep clone
|
||||
clonedEntity._noGroupPropertyTypes.CollectionChanged += clonedEntity.PropertyTypesChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
if (clonedEntity._propertyGroups != null)
|
||||
{
|
||||
clonedEntity._propertyGroups.CollectionChanged -= PropertyGroupsChanged; //clear this event handler if any
|
||||
clonedEntity._propertyGroups.ClearCollectionChangedEvents(); //clear this event handler if any
|
||||
clonedEntity._propertyGroups = (PropertyGroupCollection) _propertyGroups.DeepClone(); //manually deep clone
|
||||
clonedEntity._propertyGroups.CollectionChanged += clonedEntity.PropertyGroupsChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
@@ -34,5 +34,6 @@ namespace Umbraco.Core.Models
|
||||
void Add(IProperty property);
|
||||
|
||||
int Count { get; }
|
||||
void ClearCollectionChangedEvents();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Umbraco.Core.Models
|
||||
else
|
||||
Properties.EnsurePropertyTypes(contentType.CompositionPropertyTypes);
|
||||
|
||||
Properties.CollectionChanged -= PropertiesChanged; // be sure not to double add
|
||||
Properties.ClearCollectionChangedEvents(); // be sure not to double add
|
||||
Properties.CollectionChanged += PropertiesChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +155,8 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
public void ClearCollectionChangedEvents() => CollectionChanged = null;
|
||||
|
||||
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
CollectionChanged?.Invoke(this, args);
|
||||
|
||||
@@ -66,7 +66,10 @@ namespace Umbraco.Core.Models
|
||||
set
|
||||
{
|
||||
if (_propertyTypes != null)
|
||||
_propertyTypes.CollectionChanged -= PropertyTypesChanged;
|
||||
{
|
||||
_propertyTypes.ClearCollectionChangedEvents();
|
||||
}
|
||||
|
||||
_propertyTypes = value;
|
||||
|
||||
// since we're adding this collection to this group,
|
||||
@@ -100,7 +103,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
if (clonedEntity._propertyTypes != null)
|
||||
{
|
||||
clonedEntity._propertyTypes.CollectionChanged -= PropertyTypesChanged; //clear this event handler if any
|
||||
clonedEntity._propertyTypes.ClearCollectionChangedEvents(); //clear this event handler if any
|
||||
clonedEntity._propertyTypes = (PropertyTypeCollection) _propertyTypes.DeepClone(); //manually deep clone
|
||||
clonedEntity._propertyTypes.CollectionChanged += clonedEntity.PropertyTypesChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
@@ -160,6 +160,11 @@ namespace Umbraco.Core.Models
|
||||
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Clears all <see cref="CollectionChanged"/> event handlers
|
||||
/// </summary>
|
||||
public void ClearCollectionChangedEvents() => CollectionChanged = null;
|
||||
|
||||
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
CollectionChanged?.Invoke(this, args);
|
||||
|
||||
@@ -165,7 +165,11 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clears all <see cref="CollectionChanged"/> event handlers
|
||||
/// </summary>
|
||||
public void ClearCollectionChangedEvents() => CollectionChanged = null;
|
||||
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
CollectionChanged?.Invoke(this, args);
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
@@ -12,7 +13,7 @@ namespace Umbraco.Core.Models
|
||||
[DataContract(IsReference = true)]
|
||||
public class PublicAccessEntry : EntityBase
|
||||
{
|
||||
private readonly ObservableCollection<PublicAccessRule> _ruleCollection;
|
||||
private readonly EventClearingObservableCollection<PublicAccessRule> _ruleCollection;
|
||||
private int _protectedNodeId;
|
||||
private int _noAccessNodeId;
|
||||
private int _loginNodeId;
|
||||
@@ -28,7 +29,7 @@ namespace Umbraco.Core.Models
|
||||
NoAccessNodeId = noAccessNode.Id;
|
||||
_protectedNodeId = protectedNode.Id;
|
||||
|
||||
_ruleCollection = new ObservableCollection<PublicAccessRule>(ruleCollection);
|
||||
_ruleCollection = new EventClearingObservableCollection<PublicAccessRule>(ruleCollection);
|
||||
_ruleCollection.CollectionChanged += _ruleCollection_CollectionChanged;
|
||||
|
||||
foreach (var rule in _ruleCollection)
|
||||
@@ -44,7 +45,7 @@ namespace Umbraco.Core.Models
|
||||
NoAccessNodeId = noAccessNodeId;
|
||||
_protectedNodeId = protectedNodeId;
|
||||
|
||||
_ruleCollection = new ObservableCollection<PublicAccessRule>(ruleCollection);
|
||||
_ruleCollection = new EventClearingObservableCollection<PublicAccessRule>(ruleCollection);
|
||||
_ruleCollection.CollectionChanged += _ruleCollection_CollectionChanged;
|
||||
|
||||
foreach (var rule in _ruleCollection)
|
||||
@@ -148,7 +149,7 @@ namespace Umbraco.Core.Models
|
||||
|
||||
if (cloneEntity._ruleCollection != null)
|
||||
{
|
||||
cloneEntity._ruleCollection.CollectionChanged -= _ruleCollection_CollectionChanged; //clear this event handler if any
|
||||
cloneEntity._ruleCollection.ClearCollectionChangedEvents(); //clear this event handler if any
|
||||
cloneEntity._ruleCollection.CollectionChanged += cloneEntity._ruleCollection_CollectionChanged; //re-assign correct event handler
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +1,130 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
// <summary>The Range class. Adapted from http://stackoverflow.com/questions/5343006/is-there-a-c-sharp-type-for-representing-an-integer-range</summary>
|
||||
/// <typeparam name="T">Generic parameter.</typeparam>
|
||||
public class Range<T> where T : IComparable<T>
|
||||
/// <summary>
|
||||
/// Represents a range with a minimum and maximum value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the minimum and maximum values.</typeparam>
|
||||
/// <seealso cref="System.IEquatable{Umbraco.Core.Models.Range{T}}" />
|
||||
public class Range<T> : IEquatable<Range<T>>
|
||||
where T : IComparable<T>
|
||||
{
|
||||
/// <summary>Minimum value of the range.</summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The minimum value.
|
||||
/// </value>
|
||||
public T Minimum { get; set; }
|
||||
|
||||
/// <summary>Maximum value of the range.</summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum value.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The maximum value.
|
||||
/// </value>
|
||||
public T Maximum { get; set; }
|
||||
|
||||
/// <summary>Presents the Range in readable format.</summary>
|
||||
/// <returns>String representation of the Range</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0},{1}", this.Minimum, this.Maximum);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString() => this.ToString("{0},{1}", CultureInfo.InvariantCulture);
|
||||
|
||||
/// <summary>Determines if the range is valid.</summary>
|
||||
/// <returns>True if range is valid, else false</returns>
|
||||
public bool IsValid()
|
||||
{
|
||||
return this.Minimum.CompareTo(this.Maximum) <= 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <param name="format">A composite format string for a single value (minimum and maximum are equal). Use {0} for the minimum and {1} for the maximum value.</param>
|
||||
/// <param name="formatRange">A composite format string for the range values. Use {0} for the minimum and {1} for the maximum value.</param>
|
||||
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
public string ToString(string format, string formatRange, IFormatProvider provider = null) => this.ToString(this.Minimum.CompareTo(this.Maximum) == 0 ? format : formatRange, provider);
|
||||
|
||||
/// <summary>Determines if the provided value is inside the range.</summary>
|
||||
/// <param name="value">The value to test</param>
|
||||
/// <returns>True if the value is inside Range, else false</returns>
|
||||
public bool ContainsValue(T value)
|
||||
{
|
||||
return (this.Minimum.CompareTo(value) <= 0) && (value.CompareTo(this.Maximum) <= 0);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <param name="format">A composite format string for the range values. Use {0} for the minimum and {1} for the maximum value.</param>
|
||||
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="System.String" /> that represents this instance.
|
||||
/// </returns>
|
||||
public string ToString(string format, IFormatProvider provider = null) => string.Format(provider, format, this.Minimum, this.Maximum);
|
||||
|
||||
/// <summary>Determines if this Range is inside the bounds of another range.</summary>
|
||||
/// <param name="Range">The parent range to test on</param>
|
||||
/// <returns>True if range is inclusive, else false</returns>
|
||||
public bool IsInsideRange(Range<T> range)
|
||||
{
|
||||
return this.IsValid() && range.IsValid() && range.ContainsValue(this.Minimum) && range.ContainsValue(this.Maximum);
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether this range is valid (the minimum value is lower than or equal to the maximum value).
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this range is valid; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsValid() => this.Minimum.CompareTo(this.Maximum) <= 0;
|
||||
|
||||
/// <summary>Determines if another range is inside the bounds of this range.</summary>
|
||||
/// <param name="Range">The child range to test</param>
|
||||
/// <returns>True if range is inside, else false</returns>
|
||||
public bool ContainsRange(Range<T> range)
|
||||
{
|
||||
return this.IsValid() && range.IsValid() && this.ContainsValue(range.Minimum) && this.ContainsValue(range.Maximum);
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether this range contains the specified value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this range contains the specified value; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool ContainsValue(T value) => this.Minimum.CompareTo(value) <= 0 && value.CompareTo(this.Maximum) <= 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this range is inside the specified range.
|
||||
/// </summary>
|
||||
/// <param name="range">The range.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this range is inside the specified range; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IsInsideRange(Range<T> range) => this.IsValid() && range.IsValid() && range.ContainsValue(this.Minimum) && range.ContainsValue(this.Maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this range contains the specified range.
|
||||
/// </summary>
|
||||
/// <param name="range">The range.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if this range contains the specified range; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool ContainsRange(Range<T> range) => this.IsValid() && range.IsValid() && this.ContainsValue(range.Minimum) && this.ContainsValue(range.Maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
|
||||
/// </summary>
|
||||
/// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public override bool Equals(object obj) => obj is Range<T> other && this.Equals(other);
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the current object is equal to another object of the same type.
|
||||
/// </summary>
|
||||
/// <param name="other">An object to compare with this object.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true" /> if the current object is equal to the <paramref name="other" /> parameter; otherwise, <see langword="false" />.
|
||||
/// </returns>
|
||||
public bool Equals(Range<T> other) => other != null && this.Equals(other.Minimum, other.Maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified <paramref name="minimum" /> and <paramref name="maximum" /> values are equal to this instance values.
|
||||
/// </summary>
|
||||
/// <param name="minimum">The minimum value.</param>
|
||||
/// <param name="maximum">The maximum value.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified <paramref name="minimum" /> and <paramref name="maximum" /> values are equal to this instance values; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool Equals(T minimum, T maximum) => this.Minimum.CompareTo(minimum) == 0 && this.Maximum.CompareTo(maximum) == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hash code for this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
|
||||
/// </returns>
|
||||
public override int GetHashCode() => (this.Minimum, this.Maximum).GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user