Skip to content

Commit e7a4824

Browse files
committed
Removed tracking field for HasErrors
1 parent 28b1977 commit e7a4824

File tree

1 file changed

+19
-27
lines changed

1 file changed

+19
-27
lines changed

Microsoft.Toolkit.Mvvm/ComponentModel/ObservableValidator.cs

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,28 @@ public abstract class ObservableValidator : ObservableObject, INotifyDataErrorIn
2424
/// </summary>
2525
private readonly Dictionary<string, List<ValidationResult>> errors = new Dictionary<string, List<ValidationResult>>();
2626

27-
/// <summary>
28-
/// Indicates the total number of properties with errors (not total errors).
29-
/// This is used to allow <see cref="HasErrors"/> to operate in O(1) time, as it can just
30-
/// check whether this value is not 0 instead of having to traverse <see cref="errors"/>.
31-
/// </summary>
32-
private int totalErrors;
33-
3427
/// <inheritdoc/>
3528
public event EventHandler<DataErrorsChangedEventArgs>? ErrorsChanged;
3629

3730
/// <inheritdoc/>
38-
public bool HasErrors => this.totalErrors > 0;
31+
public bool HasErrors
32+
{
33+
get
34+
{
35+
// This uses the value enumerator for Dictionary<TKey, TValue>.ValueCollection, so it doesn't
36+
// allocate. Accessing this property is O(n), but we can stop as soon as we find at least one
37+
// error in the whole entity, and doing this saves 8 bytes in the object size (no fields needed).
38+
foreach (var value in this.errors.Values)
39+
{
40+
if (value.Count > 0)
41+
{
42+
return true;
43+
}
44+
}
45+
46+
return false;
47+
}
48+
}
3949

4050
/// <summary>
4151
/// Compares the current and new values for a given property. If the value has changed,
@@ -273,28 +283,10 @@ private void ValidateProperty(object? value, string? propertyName)
273283
new ValidationContext(this, null, null) { MemberName = propertyName },
274284
propertyErrors);
275285

276-
// Update the state and/or the errors for the property
277-
if (isValid)
278-
{
279-
if (errorsChanged)
280-
{
281-
this.totalErrors--;
282-
}
283-
}
284-
else
285-
{
286-
if (!errorsChanged)
287-
{
288-
this.totalErrors++;
289-
}
290-
291-
errorsChanged = true;
292-
}
293-
294286
// Only raise the event once if needed. This happens either when the target property
295287
// had existing errors and is now valid, or if the validation has failed and there are
296288
// new errors to broadcast, regardless of the previous validation state for the property.
297-
if (errorsChanged)
289+
if (errorsChanged || !isValid)
298290
{
299291
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
300292
}

0 commit comments

Comments
 (0)