Add nullability to Localization (#22323)

* Changes to support nullable for ns2.0
* Change ref assembly project to use nullable context
This commit is contained in:
Pranav K 2020-06-01 11:32:31 -07:00 committed by GitHub
parent 5b3976d045
commit c87d14afbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 290 additions and 60 deletions

View File

@ -28,6 +28,17 @@
</ItemGroup> </ItemGroup>
</Target> </Target>
<Choose>
<When Condition="'$(Nullable)' != '' AND ('$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFrameworkIdentifier)' == '.NETFramework')">
<PropertyGroup>
<DefineConstants>$(DefineConstants),INTERNAL_NULLABLE_ATTRIBUTES</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(SharedSourceRoot)Nullable\NullableAttributes.cs" />
</ItemGroup>
</When>
</Choose>
<Import Project="Packaging.targets" /> <Import Project="Packaging.targets" />
<Import Project="ResolveReferences.targets" /> <Import Project="ResolveReferences.targets" />

View File

@ -26,11 +26,12 @@
<_TargetFrameworkOverride /> <_TargetFrameworkOverride />
<_TargetFrameworkOverride <_TargetFrameworkOverride
Condition=" @(_ResultTargetFramework->Count()) > 1 ">%0A &lt;TargetFrameworks Condition="'%24(DotNetBuildFromSource)' == 'true'"&gt;%24(DefaultNetCoreTargetFramework)&lt;/TargetFrameworks&gt;</_TargetFrameworkOverride> Condition=" @(_ResultTargetFramework->Count()) > 1 ">%0A &lt;TargetFrameworks Condition="'%24(DotNetBuildFromSource)' == 'true'"&gt;%24(DefaultNetCoreTargetFramework)&lt;/TargetFrameworks&gt;</_TargetFrameworkOverride>
<_NullableProperty Condition="'$(Nullable)' != ''">%0A &lt;Nullable&gt;annotations&lt;/Nullable&gt;</_NullableProperty>
<ProjectListContentLines><![CDATA[ <ProjectListContentLines><![CDATA[
<!-- This file is automatically generated. --> <!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>@(_ResultTargetFramework)</TargetFrameworks>$(_TargetFrameworkOverride) <TargetFrameworks>@(_ResultTargetFramework)</TargetFrameworks>$(_TargetFrameworkOverride)$(_NullableProperty)
</PropertyGroup> </PropertyGroup>
@(ProjectListContentItem->'%(Identity)', '%0A') @(ProjectListContentItem->'%(Identity)', '%0A')
</Project> </Project>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Nullable>annotations</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="Microsoft.Extensions.Localization.Abstractions.netstandard2.0.cs" /> <Compile Include="Microsoft.Extensions.Localization.Abstractions.netstandard2.0.cs" />

View File

@ -21,10 +21,10 @@ namespace Microsoft.Extensions.Localization
{ {
public LocalizedString(string name, string value) { } public LocalizedString(string name, string value) { }
public LocalizedString(string name, string value, bool resourceNotFound) { } public LocalizedString(string name, string value, bool resourceNotFound) { }
public LocalizedString(string name, string value, bool resourceNotFound, string searchedLocation) { } public LocalizedString(string name, string value, bool resourceNotFound, string? searchedLocation) { }
public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public bool ResourceNotFound { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public bool ResourceNotFound { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string SearchedLocation { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? SearchedLocation { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public static implicit operator string (Microsoft.Extensions.Localization.LocalizedString localizedString) { throw null; } public static implicit operator string (Microsoft.Extensions.Localization.LocalizedString localizedString) { throw null; }
public override string ToString() { throw null; } public override string ToString() { throw null; }

View File

@ -21,10 +21,10 @@ namespace Microsoft.Extensions.Localization
{ {
public LocalizedString(string name, string value) { } public LocalizedString(string name, string value) { }
public LocalizedString(string name, string value, bool resourceNotFound) { } public LocalizedString(string name, string value, bool resourceNotFound) { }
public LocalizedString(string name, string value, bool resourceNotFound, string searchedLocation) { } public LocalizedString(string name, string value, bool resourceNotFound, string? searchedLocation) { }
public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public bool ResourceNotFound { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public bool ResourceNotFound { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string SearchedLocation { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string? SearchedLocation { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public static implicit operator string (Microsoft.Extensions.Localization.LocalizedString localizedString) { throw null; } public static implicit operator string (Microsoft.Extensions.Localization.LocalizedString localizedString) { throw null; }
public override string ToString() { throw null; } public override string ToString() { throw null; }

View File

@ -38,7 +38,7 @@ namespace Microsoft.Extensions.Localization
/// <param name="value">The actual string.</param> /// <param name="value">The actual string.</param>
/// <param name="resourceNotFound">Whether the string was not found in a resource. Set this to <c>true</c> to indicate an alternate string value was used.</param> /// <param name="resourceNotFound">Whether the string was not found in a resource. Set this to <c>true</c> to indicate an alternate string value was used.</param>
/// <param name="searchedLocation">The location which was searched for a localization value.</param> /// <param name="searchedLocation">The location which was searched for a localization value.</param>
public LocalizedString(string name, string value, bool resourceNotFound, string searchedLocation) public LocalizedString(string name, string value, bool resourceNotFound, string? searchedLocation)
{ {
if (name == null) if (name == null)
{ {
@ -60,7 +60,7 @@ namespace Microsoft.Extensions.Localization
/// Implicitly converts the <see cref="LocalizedString"/> to a <see cref="string"/>. /// Implicitly converts the <see cref="LocalizedString"/> to a <see cref="string"/>.
/// </summary> /// </summary>
/// <param name="localizedString">The string to be implicitly converted.</param> /// <param name="localizedString">The string to be implicitly converted.</param>
public static implicit operator string(LocalizedString localizedString) public static implicit operator string?(LocalizedString localizedString)
{ {
return localizedString?.Value; return localizedString?.Value;
} }
@ -83,7 +83,7 @@ namespace Microsoft.Extensions.Localization
/// <summary> /// <summary>
/// The location which was searched for a localization value. /// The location which was searched for a localization value.
/// </summary> /// </summary>
public string SearchedLocation { get; } public string? SearchedLocation { get; }
/// <summary> /// <summary>
/// Returns the actual string. /// Returns the actual string.

View File

@ -13,6 +13,7 @@ Microsoft.Extensions.Localization.IStringLocalizer&lt;T&gt;</Description>
<PackageTags>localization</PackageTags> <PackageTags>localization</PackageTags>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<IsAspNetCoreApp>true</IsAspNetCoreApp> <IsAspNetCoreApp>true</IsAspNetCoreApp>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -3,6 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks>netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks> <TargetFrameworks Condition="'$(DotNetBuildFromSource)' == 'true'">$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Nullable>annotations</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="Microsoft.Extensions.Localization.netstandard2.0.cs" /> <Compile Include="Microsoft.Extensions.Localization.netstandard2.0.cs" />

View File

@ -13,7 +13,7 @@ namespace Microsoft.Extensions.Localization
{ {
public partial interface IResourceNamesCache public partial interface IResourceNamesCache
{ {
System.Collections.Generic.IList<string> GetOrAdd(string name, System.Func<string, System.Collections.Generic.IList<string>> valueFactory); System.Collections.Generic.IList<string>? GetOrAdd(string name, System.Func<string, System.Collections.Generic.IList<string>?> valueFactory);
} }
public partial class LocalizationOptions public partial class LocalizationOptions
{ {
@ -35,7 +35,7 @@ namespace Microsoft.Extensions.Localization
public virtual Microsoft.Extensions.Localization.LocalizedString this[string name, params object[] arguments] { get { throw null; } } public virtual Microsoft.Extensions.Localization.LocalizedString this[string name, params object[] arguments] { get { throw null; } }
public virtual System.Collections.Generic.IEnumerable<Microsoft.Extensions.Localization.LocalizedString> GetAllStrings(bool includeParentCultures) { throw null; } public virtual System.Collections.Generic.IEnumerable<Microsoft.Extensions.Localization.LocalizedString> GetAllStrings(bool includeParentCultures) { throw null; }
protected System.Collections.Generic.IEnumerable<Microsoft.Extensions.Localization.LocalizedString> GetAllStrings(bool includeParentCultures, System.Globalization.CultureInfo culture) { throw null; } protected System.Collections.Generic.IEnumerable<Microsoft.Extensions.Localization.LocalizedString> GetAllStrings(bool includeParentCultures, System.Globalization.CultureInfo culture) { throw null; }
protected string GetStringSafely(string name, System.Globalization.CultureInfo culture) { throw null; } protected string? GetStringSafely(string name, System.Globalization.CultureInfo? culture) { throw null; }
} }
public partial class ResourceManagerStringLocalizerFactory : Microsoft.Extensions.Localization.IStringLocalizerFactory public partial class ResourceManagerStringLocalizerFactory : Microsoft.Extensions.Localization.IStringLocalizerFactory
{ {
@ -43,17 +43,17 @@ namespace Microsoft.Extensions.Localization
public Microsoft.Extensions.Localization.IStringLocalizer Create(string baseName, string location) { throw null; } public Microsoft.Extensions.Localization.IStringLocalizer Create(string baseName, string location) { throw null; }
public Microsoft.Extensions.Localization.IStringLocalizer Create(System.Type resourceSource) { throw null; } public Microsoft.Extensions.Localization.IStringLocalizer Create(System.Type resourceSource) { throw null; }
protected virtual Microsoft.Extensions.Localization.ResourceManagerStringLocalizer CreateResourceManagerStringLocalizer(System.Reflection.Assembly assembly, string baseName) { throw null; } protected virtual Microsoft.Extensions.Localization.ResourceManagerStringLocalizer CreateResourceManagerStringLocalizer(System.Reflection.Assembly assembly, string baseName) { throw null; }
protected virtual Microsoft.Extensions.Localization.ResourceLocationAttribute GetResourceLocationAttribute(System.Reflection.Assembly assembly) { throw null; } protected virtual Microsoft.Extensions.Localization.ResourceLocationAttribute? GetResourceLocationAttribute(System.Reflection.Assembly assembly) { throw null; }
protected virtual string GetResourcePrefix(System.Reflection.TypeInfo typeInfo) { throw null; } protected virtual string GetResourcePrefix(System.Reflection.TypeInfo typeInfo) { throw null; }
protected virtual string GetResourcePrefix(System.Reflection.TypeInfo typeInfo, string baseNamespace, string resourcesRelativePath) { throw null; } protected virtual string GetResourcePrefix(System.Reflection.TypeInfo typeInfo, string? baseNamespace, string? resourcesRelativePath) { throw null; }
protected virtual string GetResourcePrefix(string baseResourceName, string baseNamespace) { throw null; } protected virtual string GetResourcePrefix(string baseResourceName, string baseNamespace) { throw null; }
protected virtual string GetResourcePrefix(string location, string baseName, string resourceLocation) { throw null; } protected virtual string GetResourcePrefix(string location, string baseName, string resourceLocation) { throw null; }
protected virtual Microsoft.Extensions.Localization.RootNamespaceAttribute GetRootNamespaceAttribute(System.Reflection.Assembly assembly) { throw null; } protected virtual Microsoft.Extensions.Localization.RootNamespaceAttribute? GetRootNamespaceAttribute(System.Reflection.Assembly assembly) { throw null; }
} }
public partial class ResourceNamesCache : Microsoft.Extensions.Localization.IResourceNamesCache public partial class ResourceNamesCache : Microsoft.Extensions.Localization.IResourceNamesCache
{ {
public ResourceNamesCache() { } public ResourceNamesCache() { }
public System.Collections.Generic.IList<string> GetOrAdd(string name, System.Func<string, System.Collections.Generic.IList<string>> valueFactory) { throw null; } public System.Collections.Generic.IList<string>? GetOrAdd(string name, System.Func<string, System.Collections.Generic.IList<string>?> valueFactory) { throw null; }
} }
[System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)] [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)]
public partial class RootNamespaceAttribute : System.Attribute public partial class RootNamespaceAttribute : System.Attribute
@ -69,15 +69,15 @@ namespace Microsoft.Extensions.Localization.Internal
public AssemblyWrapper(System.Reflection.Assembly assembly) { } public AssemblyWrapper(System.Reflection.Assembly assembly) { }
public System.Reflection.Assembly Assembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public System.Reflection.Assembly Assembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public virtual string FullName { get { throw null; } } public virtual string FullName { get { throw null; } }
public virtual System.IO.Stream GetManifestResourceStream(string name) { throw null; } public virtual System.IO.Stream? GetManifestResourceStream(string name) { throw null; }
} }
public partial interface IResourceStringProvider public partial interface IResourceStringProvider
{ {
System.Collections.Generic.IList<string> GetAllResourceStrings(System.Globalization.CultureInfo culture, bool throwOnMissing); System.Collections.Generic.IList<string>? GetAllResourceStrings(System.Globalization.CultureInfo culture, bool throwOnMissing);
} }
public partial class ResourceManagerStringProvider : Microsoft.Extensions.Localization.Internal.IResourceStringProvider public partial class ResourceManagerStringProvider : Microsoft.Extensions.Localization.Internal.IResourceStringProvider
{ {
public ResourceManagerStringProvider(Microsoft.Extensions.Localization.IResourceNamesCache resourceCache, System.Resources.ResourceManager resourceManager, System.Reflection.Assembly assembly, string baseName) { } public ResourceManagerStringProvider(Microsoft.Extensions.Localization.IResourceNamesCache resourceCache, System.Resources.ResourceManager resourceManager, System.Reflection.Assembly assembly, string baseName) { }
public System.Collections.Generic.IList<string> GetAllResourceStrings(System.Globalization.CultureInfo culture, bool throwOnMissing) { throw null; } public System.Collections.Generic.IList<string>? GetAllResourceStrings(System.Globalization.CultureInfo culture, bool throwOnMissing) { throw null; }
} }
} }

View File

@ -13,7 +13,7 @@ namespace Microsoft.Extensions.Localization
{ {
public partial interface IResourceNamesCache public partial interface IResourceNamesCache
{ {
System.Collections.Generic.IList<string> GetOrAdd(string name, System.Func<string, System.Collections.Generic.IList<string>> valueFactory); System.Collections.Generic.IList<string>? GetOrAdd(string name, System.Func<string, System.Collections.Generic.IList<string>?> valueFactory);
} }
public partial class LocalizationOptions public partial class LocalizationOptions
{ {
@ -35,7 +35,7 @@ namespace Microsoft.Extensions.Localization
public virtual Microsoft.Extensions.Localization.LocalizedString this[string name, params object[] arguments] { get { throw null; } } public virtual Microsoft.Extensions.Localization.LocalizedString this[string name, params object[] arguments] { get { throw null; } }
public virtual System.Collections.Generic.IEnumerable<Microsoft.Extensions.Localization.LocalizedString> GetAllStrings(bool includeParentCultures) { throw null; } public virtual System.Collections.Generic.IEnumerable<Microsoft.Extensions.Localization.LocalizedString> GetAllStrings(bool includeParentCultures) { throw null; }
protected System.Collections.Generic.IEnumerable<Microsoft.Extensions.Localization.LocalizedString> GetAllStrings(bool includeParentCultures, System.Globalization.CultureInfo culture) { throw null; } protected System.Collections.Generic.IEnumerable<Microsoft.Extensions.Localization.LocalizedString> GetAllStrings(bool includeParentCultures, System.Globalization.CultureInfo culture) { throw null; }
protected string GetStringSafely(string name, System.Globalization.CultureInfo culture) { throw null; } protected string? GetStringSafely(string name, System.Globalization.CultureInfo? culture) { throw null; }
} }
public partial class ResourceManagerStringLocalizerFactory : Microsoft.Extensions.Localization.IStringLocalizerFactory public partial class ResourceManagerStringLocalizerFactory : Microsoft.Extensions.Localization.IStringLocalizerFactory
{ {
@ -43,17 +43,17 @@ namespace Microsoft.Extensions.Localization
public Microsoft.Extensions.Localization.IStringLocalizer Create(string baseName, string location) { throw null; } public Microsoft.Extensions.Localization.IStringLocalizer Create(string baseName, string location) { throw null; }
public Microsoft.Extensions.Localization.IStringLocalizer Create(System.Type resourceSource) { throw null; } public Microsoft.Extensions.Localization.IStringLocalizer Create(System.Type resourceSource) { throw null; }
protected virtual Microsoft.Extensions.Localization.ResourceManagerStringLocalizer CreateResourceManagerStringLocalizer(System.Reflection.Assembly assembly, string baseName) { throw null; } protected virtual Microsoft.Extensions.Localization.ResourceManagerStringLocalizer CreateResourceManagerStringLocalizer(System.Reflection.Assembly assembly, string baseName) { throw null; }
protected virtual Microsoft.Extensions.Localization.ResourceLocationAttribute GetResourceLocationAttribute(System.Reflection.Assembly assembly) { throw null; } protected virtual Microsoft.Extensions.Localization.ResourceLocationAttribute? GetResourceLocationAttribute(System.Reflection.Assembly assembly) { throw null; }
protected virtual string GetResourcePrefix(System.Reflection.TypeInfo typeInfo) { throw null; } protected virtual string GetResourcePrefix(System.Reflection.TypeInfo typeInfo) { throw null; }
protected virtual string GetResourcePrefix(System.Reflection.TypeInfo typeInfo, string baseNamespace, string resourcesRelativePath) { throw null; } protected virtual string GetResourcePrefix(System.Reflection.TypeInfo typeInfo, string? baseNamespace, string? resourcesRelativePath) { throw null; }
protected virtual string GetResourcePrefix(string baseResourceName, string baseNamespace) { throw null; } protected virtual string GetResourcePrefix(string baseResourceName, string baseNamespace) { throw null; }
protected virtual string GetResourcePrefix(string location, string baseName, string resourceLocation) { throw null; } protected virtual string GetResourcePrefix(string location, string baseName, string resourceLocation) { throw null; }
protected virtual Microsoft.Extensions.Localization.RootNamespaceAttribute GetRootNamespaceAttribute(System.Reflection.Assembly assembly) { throw null; } protected virtual Microsoft.Extensions.Localization.RootNamespaceAttribute? GetRootNamespaceAttribute(System.Reflection.Assembly assembly) { throw null; }
} }
public partial class ResourceNamesCache : Microsoft.Extensions.Localization.IResourceNamesCache public partial class ResourceNamesCache : Microsoft.Extensions.Localization.IResourceNamesCache
{ {
public ResourceNamesCache() { } public ResourceNamesCache() { }
public System.Collections.Generic.IList<string> GetOrAdd(string name, System.Func<string, System.Collections.Generic.IList<string>> valueFactory) { throw null; } public System.Collections.Generic.IList<string>? GetOrAdd(string name, System.Func<string, System.Collections.Generic.IList<string>?> valueFactory) { throw null; }
} }
[System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)] [System.AttributeUsageAttribute(System.AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)]
public partial class RootNamespaceAttribute : System.Attribute public partial class RootNamespaceAttribute : System.Attribute
@ -69,15 +69,15 @@ namespace Microsoft.Extensions.Localization.Internal
public AssemblyWrapper(System.Reflection.Assembly assembly) { } public AssemblyWrapper(System.Reflection.Assembly assembly) { }
public System.Reflection.Assembly Assembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public System.Reflection.Assembly Assembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public virtual string FullName { get { throw null; } } public virtual string FullName { get { throw null; } }
public virtual System.IO.Stream GetManifestResourceStream(string name) { throw null; } public virtual System.IO.Stream? GetManifestResourceStream(string name) { throw null; }
} }
public partial interface IResourceStringProvider public partial interface IResourceStringProvider
{ {
System.Collections.Generic.IList<string> GetAllResourceStrings(System.Globalization.CultureInfo culture, bool throwOnMissing); System.Collections.Generic.IList<string>? GetAllResourceStrings(System.Globalization.CultureInfo culture, bool throwOnMissing);
} }
public partial class ResourceManagerStringProvider : Microsoft.Extensions.Localization.Internal.IResourceStringProvider public partial class ResourceManagerStringProvider : Microsoft.Extensions.Localization.Internal.IResourceStringProvider
{ {
public ResourceManagerStringProvider(Microsoft.Extensions.Localization.IResourceNamesCache resourceCache, System.Resources.ResourceManager resourceManager, System.Reflection.Assembly assembly, string baseName) { } public ResourceManagerStringProvider(Microsoft.Extensions.Localization.IResourceNamesCache resourceCache, System.Resources.ResourceManager resourceManager, System.Reflection.Assembly assembly, string baseName) { }
public System.Collections.Generic.IList<string> GetAllResourceStrings(System.Globalization.CultureInfo culture, bool throwOnMissing) { throw null; } public System.Collections.Generic.IList<string>? GetAllResourceStrings(System.Globalization.CultureInfo culture, bool throwOnMissing) { throw null; }
} }
} }

View File

@ -17,6 +17,6 @@ namespace Microsoft.Extensions.Localization
/// <param name="name">The resource name to add string names for.</param> /// <param name="name">The resource name to add string names for.</param>
/// <param name="valueFactory">The function used to generate the string names for the resource.</param> /// <param name="valueFactory">The function used to generate the string names for the resource.</param>
/// <returns>The string names for the resource.</returns> /// <returns>The string names for the resource.</returns>
IList<string> GetOrAdd(string name, Func<string, IList<string>> valueFactory); IList<string>? GetOrAdd(string name, Func<string, IList<string>?> valueFactory);
} }
} }

View File

@ -25,8 +25,8 @@ namespace Microsoft.Extensions.Localization.Internal
public Assembly Assembly { get; } public Assembly Assembly { get; }
public virtual string FullName => Assembly.FullName; public virtual string FullName => Assembly.FullName!;
public virtual Stream GetManifestResourceStream(string name) => Assembly.GetManifestResourceStream(name); public virtual Stream? GetManifestResourceStream(string name) => Assembly.GetManifestResourceStream(name);
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic; using System.Collections.Generic;
@ -12,6 +12,6 @@ namespace Microsoft.Extensions.Localization.Internal
/// </summary> /// </summary>
public interface IResourceStringProvider public interface IResourceStringProvider
{ {
IList<string> GetAllResourceStrings(CultureInfo culture, bool throwOnMissing); IList<string>? GetAllResourceStrings(CultureInfo culture, bool throwOnMissing);
} }
} }

View File

@ -9,7 +9,7 @@ namespace Microsoft.Extensions.Localization.Internal
{ {
internal static class ResourceManagerStringLocalizerLoggerExtensions internal static class ResourceManagerStringLocalizerLoggerExtensions
{ {
private static readonly Action<ILogger, string, string, CultureInfo, Exception> _searchedLocation; private static readonly Action<ILogger, string, string, CultureInfo, Exception?> _searchedLocation;
static ResourceManagerStringLocalizerLoggerExtensions() static ResourceManagerStringLocalizerLoggerExtensions()
{ {

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections; using System.Collections;
@ -51,7 +51,7 @@ namespace Microsoft.Extensions.Localization.Internal
return resourceStreamName; return resourceStreamName;
} }
public IList<string> GetAllResourceStrings(CultureInfo culture, bool throwOnMissing) public IList<string>? GetAllResourceStrings(CultureInfo culture, bool throwOnMissing)
{ {
var cacheKey = GetResourceCacheKey(culture); var cacheKey = GetResourceCacheKey(culture);
@ -72,9 +72,12 @@ namespace Microsoft.Extensions.Localization.Internal
} }
var names = new List<string>(); var names = new List<string>();
foreach (DictionaryEntry entry in resourceSet) foreach (DictionaryEntry? entry in resourceSet)
{ {
names.Add((string)entry.Key); if (entry?.Key is string key)
{
names.Add(key);
}
} }
return names; return names;

View File

@ -10,6 +10,7 @@
<PackageTags>localization</PackageTags> <PackageTags>localization</PackageTags>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<IsAspNetCoreApp>true</IsAspNetCoreApp> <IsAspNetCoreApp>true</IsAspNetCoreApp>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Resources; using System.Resources;
using Microsoft.Extensions.Localization.Internal; using Microsoft.Extensions.Localization.Internal;
@ -19,7 +20,7 @@ namespace Microsoft.Extensions.Localization
/// <remarks>This type is thread-safe.</remarks> /// <remarks>This type is thread-safe.</remarks>
public class ResourceManagerStringLocalizer : IStringLocalizer public class ResourceManagerStringLocalizer : IStringLocalizer
{ {
private readonly ConcurrentDictionary<string, object> _missingManifestCache = new ConcurrentDictionary<string, object>(); private readonly ConcurrentDictionary<string, object?> _missingManifestCache = new ConcurrentDictionary<string, object?>();
private readonly IResourceNamesCache _resourceNamesCache; private readonly IResourceNamesCache _resourceNamesCache;
private readonly ResourceManager _resourceManager; private readonly ResourceManager _resourceManager;
private readonly IResourceStringProvider _resourceStringProvider; private readonly IResourceStringProvider _resourceStringProvider;
@ -171,7 +172,7 @@ namespace Microsoft.Extensions.Localization
? GetResourceNamesFromCultureHierarchy(culture) ? GetResourceNamesFromCultureHierarchy(culture)
: _resourceStringProvider.GetAllResourceStrings(culture, true); : _resourceStringProvider.GetAllResourceStrings(culture, true);
foreach (var name in resourceNames) foreach (var name in resourceNames ?? Enumerable.Empty<string>())
{ {
var value = GetStringSafely(name, culture); var value = GetStringSafely(name, culture);
yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _resourceBaseName); yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _resourceBaseName);
@ -185,7 +186,7 @@ namespace Microsoft.Extensions.Localization
/// <param name="name">The name of the string resource.</param> /// <param name="name">The name of the string resource.</param>
/// <param name="culture">The <see cref="CultureInfo"/> to get the string for.</param> /// <param name="culture">The <see cref="CultureInfo"/> to get the string for.</param>
/// <returns>The resource string, or <c>null</c> if none was found.</returns> /// <returns>The resource string, or <c>null</c> if none was found.</returns>
protected string GetStringSafely(string name, CultureInfo culture) protected string? GetStringSafely(string name, CultureInfo? culture)
{ {
if (name == null) if (name == null)
{ {

View File

@ -82,7 +82,7 @@ namespace Microsoft.Extensions.Localization
/// For the type "Sample.Controllers.Home" if there's a resourceRelativePath return /// For the type "Sample.Controllers.Home" if there's a resourceRelativePath return
/// "Sample.Resourcepath.Controllers.Home" if there isn't one then it would return "Sample.Controllers.Home". /// "Sample.Resourcepath.Controllers.Home" if there isn't one then it would return "Sample.Controllers.Home".
/// </remarks> /// </remarks>
protected virtual string GetResourcePrefix(TypeInfo typeInfo, string baseNamespace, string resourcesRelativePath) protected virtual string GetResourcePrefix(TypeInfo typeInfo, string? baseNamespace, string? resourcesRelativePath)
{ {
if (typeInfo == null) if (typeInfo == null)
{ {
@ -94,6 +94,11 @@ namespace Microsoft.Extensions.Localization
throw new ArgumentNullException(nameof(baseNamespace)); throw new ArgumentNullException(nameof(baseNamespace));
} }
if (string.IsNullOrEmpty(typeInfo.FullName))
{
throw new ArgumentException(Resources.FormatLocalization_TypeMustHaveTypeName(typeInfo));
}
if (string.IsNullOrEmpty(resourcesRelativePath)) if (string.IsNullOrEmpty(resourcesRelativePath))
{ {
return typeInfo.FullName; return typeInfo.FullName;
@ -219,7 +224,7 @@ namespace Microsoft.Extensions.Localization
/// <param name="assembly">The assembly to get a <see cref="ResourceLocationAttribute"/> from.</param> /// <param name="assembly">The assembly to get a <see cref="ResourceLocationAttribute"/> from.</param>
/// <returns>The <see cref="ResourceLocationAttribute"/> associated with the given <see cref="Assembly"/>.</returns> /// <returns>The <see cref="ResourceLocationAttribute"/> associated with the given <see cref="Assembly"/>.</returns>
/// <remarks>This method is protected and virtual for testing purposes only.</remarks> /// <remarks>This method is protected and virtual for testing purposes only.</remarks>
protected virtual ResourceLocationAttribute GetResourceLocationAttribute(Assembly assembly) protected virtual ResourceLocationAttribute? GetResourceLocationAttribute(Assembly assembly)
{ {
return assembly.GetCustomAttribute<ResourceLocationAttribute>(); return assembly.GetCustomAttribute<ResourceLocationAttribute>();
} }
@ -228,17 +233,21 @@ namespace Microsoft.Extensions.Localization
/// <param name="assembly">The assembly to get a <see cref="RootNamespaceAttribute"/> from.</param> /// <param name="assembly">The assembly to get a <see cref="RootNamespaceAttribute"/> from.</param>
/// <returns>The <see cref="RootNamespaceAttribute"/> associated with the given <see cref="Assembly"/>.</returns> /// <returns>The <see cref="RootNamespaceAttribute"/> associated with the given <see cref="Assembly"/>.</returns>
/// <remarks>This method is protected and virtual for testing purposes only.</remarks> /// <remarks>This method is protected and virtual for testing purposes only.</remarks>
protected virtual RootNamespaceAttribute GetRootNamespaceAttribute(Assembly assembly) protected virtual RootNamespaceAttribute? GetRootNamespaceAttribute(Assembly assembly)
{ {
return assembly.GetCustomAttribute<RootNamespaceAttribute>(); return assembly.GetCustomAttribute<RootNamespaceAttribute>();
} }
private string GetRootNamespace(Assembly assembly) private string? GetRootNamespace(Assembly assembly)
{ {
var rootNamespaceAttribute = GetRootNamespaceAttribute(assembly); var rootNamespaceAttribute = GetRootNamespaceAttribute(assembly);
return rootNamespaceAttribute?.RootNamespace ?? if (rootNamespaceAttribute != null)
new AssemblyName(assembly.FullName).Name; {
return rootNamespaceAttribute.RootNamespace;
}
return assembly.GetName().Name;
} }
private string GetResourcePath(Assembly assembly) private string GetResourcePath(Assembly assembly)
@ -256,7 +265,7 @@ namespace Microsoft.Extensions.Localization
return resourceLocation; return resourceLocation;
} }
private static string TrimPrefix(string name, string prefix) private static string? TrimPrefix(string name, string prefix)
{ {
if (name.StartsWith(prefix, StringComparison.Ordinal)) if (name.StartsWith(prefix, StringComparison.Ordinal))
{ {

View File

@ -12,7 +12,7 @@ namespace Microsoft.Extensions.Localization
/// </summary> /// </summary>
public class ResourceNamesCache : IResourceNamesCache public class ResourceNamesCache : IResourceNamesCache
{ {
private readonly ConcurrentDictionary<string, IList<string>> _cache = new ConcurrentDictionary<string, IList<string>>(); private readonly ConcurrentDictionary<string, IList<string>?> _cache = new ConcurrentDictionary<string, IList<string>?>();
/// <summary> /// <summary>
/// Creates a new <see cref="ResourceNamesCache" /> /// Creates a new <see cref="ResourceNamesCache" />
@ -22,7 +22,7 @@ namespace Microsoft.Extensions.Localization
} }
/// <inheritdoc /> /// <inheritdoc />
public IList<string> GetOrAdd(string name, Func<string, IList<string>> valueFactory) public IList<string>? GetOrAdd(string name, Func<string, IList<string>?> valueFactory)
{ {
return _cache.GetOrAdd(name, valueFactory); return _cache.GetOrAdd(name, valueFactory);
} }

View File

@ -123,4 +123,7 @@
<data name="Localization_MissingManifest_Parent" xml:space="preserve"> <data name="Localization_MissingManifest_Parent" xml:space="preserve">
<value>No manifests exist for the current culture.</value> <value>No manifests exist for the current culture.</value>
</data> </data>
<data name="Localization_TypeMustHaveTypeName" xml:space="preserve">
<value>Type '{0}' must have a non-null type name.</value>
</data>
</root> </root>

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks> <TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
<RootNamespace>LocalizationTest.Abc</RootNamespace> <RootNamespace>LocalizationTest.Abc</RootNamespace>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="NewFolder\**" /> <Compile Remove="NewFolder\**" />

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks> <TargetFrameworks>$(DefaultNetCoreTargetFramework);net472</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable disable
using System; using System;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
@ -84,7 +85,7 @@ namespace Microsoft.Extensions.Localization.Tests
// Assert // Assert
Assert.Equal(typeFactory.BaseName, stringFactory.BaseName); Assert.Equal(typeFactory.BaseName, stringFactory.BaseName);
Assert.Equal(typeFactory.Assembly.FullName, stringFactory.Assembly.FullName); Assert.Equal(typeFactory.Assembly!.FullName, stringFactory.Assembly!.FullName);
} }
[Fact] [Fact]
@ -293,7 +294,7 @@ namespace Microsoft.Extensions.Localization.Tests
var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory); var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory);
// Act & Assert // Act & Assert
Assert.Throws<ArgumentNullException>(() => factory.Create("baseName", location: null)); Assert.Throws<ArgumentNullException>(() => factory.Create("baseName", location: null!));
} }
} }
} }

View File

@ -249,9 +249,9 @@ namespace Microsoft.Extensions.Localization
_assemblyWrapper = assemblyWrapper; _assemblyWrapper = assemblyWrapper;
} }
public override string GetString(string name, CultureInfo culture) => null; public override string? GetString(string name, CultureInfo? culture) => null;
public override ResourceSet GetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) public override ResourceSet? GetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{ {
var resourceStream = _assemblyWrapper.GetManifestResourceStream(BaseName); var resourceStream = _assemblyWrapper.GetManifestResourceStream(BaseName);
@ -287,7 +287,7 @@ namespace Microsoft.Extensions.Localization
public int ManifestResourceStreamCallCount { get; private set; } public int ManifestResourceStreamCallCount { get; private set; }
public override Stream GetManifestResourceStream(string name) public override Stream? GetManifestResourceStream(string name)
{ {
ManifestResourceStreamCallCount++; ManifestResourceStreamCallCount++;

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Globalization;
using Moq; using Moq;
using Xunit; using Xunit;
@ -15,7 +14,7 @@ namespace Microsoft.Extensions.Localization
{ {
// Arrange, act and assert // Arrange, act and assert
var exception = Assert.Throws<ArgumentNullException>( var exception = Assert.Throws<ArgumentNullException>(
() => new StringLocalizer<object>(factory: null)); () => new StringLocalizer<object>(factory: null!));
Assert.Equal("factory", exception.ParamName); Assert.Equal("factory", exception.ParamName);
} }
@ -45,7 +44,7 @@ namespace Microsoft.Extensions.Localization
var localizer = new StringLocalizer<object>(factory.Object); var localizer = new StringLocalizer<object>(factory.Object);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => localizer[name: null]); var exception = Assert.Throws<ArgumentNullException>(() => localizer[name: null!]);
Assert.Equal("name", exception.ParamName); Assert.Equal("name", exception.ParamName);
} }
@ -80,7 +79,7 @@ namespace Microsoft.Extensions.Localization
var localizer = new StringLocalizer<object>(factory.Object); var localizer = new StringLocalizer<object>(factory.Object);
// Act and assert // Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => localizer[name: null]); var exception = Assert.Throws<ArgumentNullException>(() => localizer[name: null!]);
Assert.Equal("name", exception.ParamName); Assert.Equal("name", exception.ParamName);
} }

View File

@ -0,0 +1,196 @@
// 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.
// From https://github.com/dotnet/runtime/blob/ef72b95937703e485fdbbb75f3251fedfd1a0ef9/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>Specifies that null is allowed as an input even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class AllowNullAttribute : Attribute { }
/// <summary>Specifies that null is disallowed as an input even if the corresponding type allows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class DisallowNullAttribute : Attribute { }
/// <summary>Specifies that an output may be null even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class MaybeNullAttribute : Attribute { }
/// <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>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class NotNullAttribute : Attribute { }
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter may be null even if the corresponding type disallows it.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class MaybeNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter may be null.
/// </param>
public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
}
/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class NotNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
}
/// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class NotNullIfNotNullAttribute : Attribute
{
/// <summary>Initializes the attribute with the associated parameter name.</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; }
}
/// <summary>Applied to a method that will never return under any circumstance.</summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class DoesNotReturnAttribute : Attribute { }
/// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class DoesNotReturnIfAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified parameter value.</summary>
/// <param name="parameterValue">
/// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to
/// the associated parameter matches this value.
/// </param>
public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue;
/// <summary>Gets the condition parameter value.</summary>
public bool ParameterValue { get; }
}
/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values.</summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class MemberNotNullAttribute : Attribute
{
/// <summary>Initializes the attribute with a field or property member.</summary>
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
public MemberNotNullAttribute(string member) => Members = new[] { member };
/// <summary>Initializes the attribute with the list of field and property members.</summary>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullAttribute(params string[] members) => Members = members;
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
}
/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values when returning with the specified return value condition.</summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
#if INTERNAL_NULLABLE_ATTRIBUTES
internal
#else
public
#endif
sealed class MemberNotNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition and a field or property member.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
/// <param name="member">
/// The field or property member that is promised to be not-null.
/// </param>
public MemberNotNullWhenAttribute(bool returnValue, string member)
{
ReturnValue = returnValue;
Members = new[] { member };
}
/// <summary>Initializes the attribute with the specified return value condition and list of field and property members.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
/// <param name="members">
/// The list of field and property members that are promised to be not-null.
/// </param>
public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
{
ReturnValue = returnValue;
Members = members;
}
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
/// <summary>Gets field or property member names.</summary>
public string[] Members { get; }
}
}