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

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

问题描述

对于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.

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

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