返回类型为“字符串"的函数返回一个可为空的字符串(即“字符串?") [英] Function with return type of 'string' returns a nullable string (ie 'string?')

查看:36
本文介绍了返回类型为“字符串"的函数返回一个可为空的字符串(即“字符串?")的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于 Azure Functions 项目,我使用的是启用了可为空引用类型的 C# 8.由于 AzureFunctions AppSettings 通过环境变量公开,环境变量可以是字符串或空值(即它们返回 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 将在 Quick Info 中向您显示编译器为您的变量推断的空状态(通过将鼠标悬停在变量上):

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());

在上面的例子中,sstring? 类型,但是编译器在每一点都知道它是否可以包含 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.

这篇关于返回类型为“字符串"的函数返回一个可为空的字符串(即“字符串?")的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆