Added more nullability annotations to helper methods

This commit is contained in:
Sergio Pedri 2021-07-27 15:58:06 +02:00
Родитель 7b49dae015
Коммит 253cb963b5
5 изменённых файлов: 60 добавлений и 10 удалений

Просмотреть файл

@ -0,0 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NETSTANDARD2_0
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// Specifies that an output will not be null even if the corresponding type allows it.
/// Specifies that an input argument was not null when the call returns.
/// </summary>
/// <remarks>Internal copy from the BCL attribute.</remarks>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
internal sealed class NotNullAttribute : Attribute
{
}
}
#endif

Просмотреть файл

@ -0,0 +1,27 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NETSTANDARD2_0
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// Specifies that the output will be non-null if the named parameter is non-null.
/// </summary>
/// <remarks>Internal copy from the BCL attribute.</remarks>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
internal sealed class NotNullIfNotNullAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="NotNullIfNotNullAttribute"/> class.
/// </summary>
/// <param name="parameterName"> The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null.</param>
public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName;
/// <summary>Gets the associated parameter name.</summary>
public string ParameterName { get; }
}
}
#endif

Просмотреть файл

@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@ -84,7 +85,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// The <see cref="PropertyChanging"/> and <see cref="PropertyChanged"/> events are not raised
/// if the current and new value for the target property are the same.
/// </remarks>
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string? propertyName = null)
protected bool SetProperty<T>([NotNullIfNotNull("newValue")] ref T field, T newValue, [CallerMemberName] string? propertyName = null)
{
// We duplicate the code here instead of calling the overload because we can't
// guarantee that the invoked SetProperty<T> will be inlined, and we need the JIT
@ -120,7 +121,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// <param name="comparer">The <see cref="IEqualityComparer{T}"/> instance to use to compare the input values.</param>
/// <param name="propertyName">(optional) The name of the property that changed.</param>
/// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
protected bool SetProperty<T>(ref T field, T newValue, IEqualityComparer<T> comparer, [CallerMemberName] string? propertyName = null)
protected bool SetProperty<T>([NotNullIfNotNull("newValue")] ref T field, T newValue, IEqualityComparer<T> comparer, [CallerMemberName] string? propertyName = null)
{
if (comparer.Equals(field, newValue))
{
@ -340,7 +341,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// indicates that the new value being assigned to <paramref name="taskNotifier"/> is different than the previous one,
/// and it does not mean the new <see cref="Task"/> instance passed as argument is in any particular state.
/// </remarks>
protected bool SetPropertyAndNotifyOnCompletion(ref TaskNotifier? taskNotifier, Task? newValue, [CallerMemberName] string? propertyName = null)
protected bool SetPropertyAndNotifyOnCompletion([NotNull] ref TaskNotifier? taskNotifier, Task? newValue, [CallerMemberName] string? propertyName = null)
{
// We invoke the overload with a callback here to avoid code duplication, and simply pass an empty callback.
// The lambda expression here is transformed by the C# compiler into an empty closure class with a
@ -368,7 +369,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// The <see cref="PropertyChanging"/> and <see cref="PropertyChanged"/> events are not raised
/// if the current and new value for the target property are the same.
/// </remarks>
protected bool SetPropertyAndNotifyOnCompletion(ref TaskNotifier? taskNotifier, Task? newValue, Action<Task?> callback, [CallerMemberName] string? propertyName = null)
protected bool SetPropertyAndNotifyOnCompletion([NotNull] ref TaskNotifier? taskNotifier, Task? newValue, Action<Task?> callback, [CallerMemberName] string? propertyName = null)
{
return SetPropertyAndNotifyOnCompletion(taskNotifier ??= new(), newValue, callback, propertyName);
}
@ -407,7 +408,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// indicates that the new value being assigned to <paramref name="taskNotifier"/> is different than the previous one,
/// and it does not mean the new <see cref="Task{TResult}"/> instance passed as argument is in any particular state.
/// </remarks>
protected bool SetPropertyAndNotifyOnCompletion<T>(ref TaskNotifier<T>? taskNotifier, Task<T>? newValue, [CallerMemberName] string? propertyName = null)
protected bool SetPropertyAndNotifyOnCompletion<T>([NotNull] ref TaskNotifier<T>? taskNotifier, Task<T>? newValue, [CallerMemberName] string? propertyName = null)
{
return SetPropertyAndNotifyOnCompletion(taskNotifier ??= new(), newValue, static _ => { }, propertyName);
}
@ -430,7 +431,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// The <see cref="PropertyChanging"/> and <see cref="PropertyChanged"/> events are not raised
/// if the current and new value for the target property are the same.
/// </remarks>
protected bool SetPropertyAndNotifyOnCompletion<T>(ref TaskNotifier<T>? taskNotifier, Task<T>? newValue, Action<Task<T>?> callback, [CallerMemberName] string? propertyName = null)
protected bool SetPropertyAndNotifyOnCompletion<T>([NotNull] ref TaskNotifier<T>? taskNotifier, Task<T>? newValue, Action<Task<T>?> callback, [CallerMemberName] string? propertyName = null)
{
return SetPropertyAndNotifyOnCompletion(taskNotifier ??= new(), newValue, callback, propertyName);
}

Просмотреть файл

@ -16,6 +16,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Mvvm.Messaging;
using Microsoft.Toolkit.Mvvm.Messaging.Messages;
@ -145,7 +146,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// the <see cref="ObservableObject.PropertyChanging"/> and <see cref="ObservableObject.PropertyChanged"/> events
/// are not raised if the current and new value for the target property are the same.
/// </remarks>
protected bool SetProperty<T>(ref T field, T newValue, bool broadcast, [CallerMemberName] string? propertyName = null)
protected bool SetProperty<T>([NotNullIfNotNull("newValue")] ref T field, T newValue, bool broadcast, [CallerMemberName] string? propertyName = null)
{
T oldValue = field;
@ -174,7 +175,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// <param name="broadcast">If <see langword="true"/>, <see cref="Broadcast{T}"/> will also be invoked.</param>
/// <param name="propertyName">(optional) The name of the property that changed.</param>
/// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
protected bool SetProperty<T>(ref T field, T newValue, IEqualityComparer<T> comparer, bool broadcast, [CallerMemberName] string? propertyName = null)
protected bool SetProperty<T>([NotNullIfNotNull("newValue")] ref T field, T newValue, IEqualityComparer<T> comparer, bool broadcast, [CallerMemberName] string? propertyName = null)
{
T oldValue = field;

Просмотреть файл

@ -7,6 +7,7 @@ using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;
@ -137,7 +138,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// the <see cref="ObservableObject.PropertyChanging"/> and <see cref="ObservableObject.PropertyChanged"/> events
/// are not raised if the current and new value for the target property are the same.
/// </remarks>
protected bool SetProperty<T>(ref T field, T newValue, bool validate, [CallerMemberName] string? propertyName = null)
protected bool SetProperty<T>([NotNullIfNotNull("newValue")] ref T field, T newValue, bool validate, [CallerMemberName] string? propertyName = null)
{
bool propertyChanged = SetProperty(ref field, newValue, propertyName);
@ -162,7 +163,7 @@ namespace Microsoft.Toolkit.Mvvm.ComponentModel
/// <param name="validate">If <see langword="true"/>, <paramref name="newValue"/> will also be validated.</param>
/// <param name="propertyName">(optional) The name of the property that changed.</param>
/// <returns><see langword="true"/> if the property was changed, <see langword="false"/> otherwise.</returns>
protected bool SetProperty<T>(ref T field, T newValue, IEqualityComparer<T> comparer, bool validate, [CallerMemberName] string? propertyName = null)
protected bool SetProperty<T>([NotNullIfNotNull("newValue")] ref T field, T newValue, IEqualityComparer<T> comparer, bool validate, [CallerMemberName] string? propertyName = null)
{
bool propertyChanged = SetProperty(ref field, newValue, comparer, propertyName);