返回类型为“字符串"的函数将返回可为空的字符串(即“字符串?")
对于Azure Functions项目,我正在使用具有启用的可空引用类型的C#8.由于使用AzureFunctions AppSettings是通过环境变量公开的,环境变量可以是字符串或null(即它们返回 string?
),因此我试图封装获取环境变量的逻辑-如果它们是未设置-设置为单独的方法 GetEnvVariable
.
For an Azure Functions project I am using C# 8 with enabled nullable reference types. Since with AzureFunctions AppSettings are exposed via environment variables, which can be a string or null (i.e. they return string?
) I tried to encapsulate the logic of getting environment variables - and throwing an error if they're not set - into a separate method GetEnvVariable
.
如您所见, GetEnvVariable
通过三行简短的代码实现.如果未设置环境变量(即为 null
),则会引发自定义异常,否则将字符串值返回.
As you can see, GetEnvVariable
is implemented in three short lines. If the environment variable is not set (i.e it is null
) it throws a custom exception, else the string value is returned.
以下行未显示可能取消引用null"的问题,因为编译器知道,在此行 env
必须为 string
(不是 string?
),因为该异常将已经触发并且无法到达此行.
The following line does not show a problem of "possible de-reference of null" because the compiler know, that at this line env
must be string
(not string?
) because the exception would have fired already and this line could not have been reached.
var length = env.Contains('$');
var length = env.Contains('$');
仍然,当用鼠标悬停在变量 env
上时,类型显示为 string?
Still, when hovering over the variable env
with the mouse the type is displayed as string?
这有意义吗?如果是这样,为什么?为 env
分配了 GetEnvVariable
方法的输出,该方法返回 string
.
Does this make sense? If so, why? env
is assigned the output of the GetEnvVariable
method, which return string
.
引发异常是否隐式返回 null
?请帮助我理解,非常感谢您的投入.干杯!
Does throwing an exception implicitly return null
? Please help me understand, your input is really appreciated. Cheers!
这是我的代码
namespace delme_azf
{
public static class kv
{
[FunctionName("kv")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
ILogger log)
{
try
{
var envName = "lolomat";
var env = GetEnvVariable(envName);
var length = env.Contains('$');
return new OkObjectResult($"success {env}");
}
catch (System.Exception)
{
throw;
}
}
public static string GetEnvVariable(string name)
{
var env = Environment.GetEnvironmentVariable(name);
if (env == null) throw new EnvironmentVariableNotSetException(nameof(name));
return env;
}
public class EnvironmentVariableNotSetException : Exception
{
public EnvironmentVariableNotSetException() {}
public EnvironmentVariableNotSetException(string envName) : base($"Mandatory environment variable '{envName}' is not set.") {}
}
}
}
这也是我完整的* .csproj,显示了可空引用类型已全局启用.
Also here's my full *.csproj showing that nullable reference types are enabled globally.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>8.0</LangVersion>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
<RootNamespace>delme_azf</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.3" />
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="2.19.70" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
抛出异常不会使您的方法返回null或任何其他值.
Throwing an exception does not make your method return null or any other value.
当您声明引用类型的 var
时,编译器将始终为其推断可为null的类型.这样做的原因是,编译器完全了解该变量在方法中的任何位置是否可以包含null,因此,如果您要执行以下操作,则编译器可以了解您的操作并留下来挡路:
When you declare a var
of a reference type, the compiler will always infer a nullable type for it. The reason for this is that the compiler has full knowledge of whether or not the variable could contain null at any point in the method--so if you wanted to do something like the following, the compiler can understand what you're doing and stay out of your way:
var x = "initial value";
Console.WriteLine(x.ToString()); // ok
if (someCondition)
{
// there's no warning on this assignment, because
// `var x` was inferred to have a `string?` type in the beginning.
x = null;
}
CarryOnWith(x); // ok, assuming the method accepts a possibly null string
Visual Studio将向您显示编译器为快速信息中的变量推断出的空状态(将鼠标悬停在变量上):
Visual Studio will show you the null state the compiler has inferred for your variable in Quick Info (by hovering over the variable):
另请参阅C#设计团队的注释,说明了使 var
始终推断可为空的引用类型的决定.
See also the notes from the C# design team on the decision to make var
always infer a nullable reference type.
下面是有关该语言正在做什么的更多上下文:
Below is some more context on what the language is doing:
可空性分析同时跟踪变量的声明类型和变量的流状态.考虑如下示例:
Nullability analysis tracks both the declared type of a variable and the flow state of a variable. Consider an example like the following:
string? s = null;
if (s != null)
{
// if we somehow got here, s was not null.
Console.WriteLine(s.ToString());
}
else
{
// warning: dereference of a possibly null reference
Console.WriteLine(s.ToString());
}
s = "hello";
// since we know a not-null was assigned, we now know this is safe.
Console.WriteLine(s.ToString());
// additionally the flow state becomes not-null if
// a null value would have definitely caused an exception earlier on:
s = null;
// warning
Console.WriteLine(s.ToString());
// no warning, because the previous line would have already thrown an exception
Console.WriteLine(s.ToString());
在上面的示例中, s
的类型为 string?
,但是编译器在每个点都知道它是否可以包含 null
-因此可以访问其成员或将其传递给需要 string
参数的方法.
In the above example, s
is of type string?
, but the compiler knows at each point whether or not it could contain null
-- so it's OK to access members on it or pass it off to methods that require a string
argument.