How to shut the warning up when using the combination of Blazor code-behind, property injection, and C# nullable reference types
Tags: blazor, csharp, dotnet
Published: 2021-04-25 07:09:40

# Introduction

 
##  C# nullable reference types

Since C# 8.0, we can use the "nullable reference types" feature on C# programming.

It helps us to build more robust applications on C#.

Adding the `<Nullable>enable</Nullabl>` MSBuild property value into the C# project file (.csproj ) is one of the ways to enable this feature.

```xml
<!-- This is .csproj file -->
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    ...
    <!-- 👇 Add this line -->
    <Nullable>enable</Nullable>
    ....
```

## Code-behind in Blazor programming

In Blazor programming, to implement a component, we usually write an HTML markup and C# code mixing in a Razor file (.razor), and place a C# code inside a `@code { }` block.

```html
<!-- This is MyComponent.razor file -->
<p>Here is an HTML markup.</p>

@code {
  // Here is a C# code block.
}
```

And another way we can use the "code-behind" way.
In this way, we write a C# code in a usual C# source file (.cs) as a partial class.

```csharp
// This is MyComponent.razor.cs file
public class partial MyComponent
{
  // Here is a C# code separated from the .razor file
}
```

Sometimes the "code-behind" style is convenient to make a Blazor component readable and maintainable.

## Dependency Injection in a "code-behind" of a Blazor component

We have to use the `@inject` directive in a Blazor component (.razor) to retrieve any service from the DI container.

```html
<!-- This is MyComponent.razor file -->

<!-- 👇 The "IJSRuntime" service instance will be injected 
          from DI container. -->
@inject IJSRuntime JS
```

`@inject` directives work as property injection.

So if you want to inject a service in a "code-behind" C# source file, you can do it with a property that is annotated with `[Inject]` attribute instead of the `@inject` directive.

```csharp
// This is MyComponent.razor.cs file
public class partial MyComponent
{
  // 👇 The "IJSRuntime" service instance will be injected 
  //    from DI container.
  [Inject]
  private IJSRuntime JS { get; set; }
  ...
```


# What happens if we mix these 3 programming styles?

If we mix these three programming factors - C# nullable reference type, code-behind style, property injection in code-behind - what will happen?

The answer is, **it causes a terrible warning, "CS8618".**

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/24o40ym882j65h43a5vv.png)

> _"Warning CS8618	Non-nullable property 'JS' must contain a non-null value when exiting constructor. Consider declaring the property as nullable."_

However, in my understanding, the property that will be injected from the DI container might never be null where the code place that the application developer will write.

So I feel this CS8618 warning does not make sense.

What can we do to avoid this warning?

# I have three ideas (but are not perfect solution) + _[May 2, 2021, Updated]_ One more good idea I heard from others

I'm not sure about the perfect solution to this problem at this time.

But I came up with three ideas to mitigate the problem.

_**[May 2, 2021, Updated]** I heard one more good idea from [@taks](https://github.com/taks).
So I added that method I heard into the list below._ 

## 1. Make the property nullable.

One of the ideas is to make the property nullable.
To do this, append the "?" symbol to the end of the type name.

```csharp
[Inject]     // 👇 "?" means this property can be null.
public IJSRuntime? JS { get; set; }
```

Instead, we have to do a null-check whenever before referencing the property.

```csharp
// 👇 It required to perform null-check.
if (this.JS != null)
{
    await this.JS.InvokeVoidAsync("foo");
}
```

(If we do not this, the C# compiler raise another warning "CS8604".)

This solution is strictly the right way.  
But as I said before, the injected property will never be null in the developer's code as a practical matter.

So I feel this solution is too redundant.

We also can use the "!" symbol to make the C# compiler ignore the condition that the variable is null or not.

```csharp
//          👇 The "!" symbol suppresses the null state check.
await this.JS!.InvokeVoidAsync("foo");
```

But I do not prefer this way because this way loses the benefits of the nullable reference type feature.

## 2. Add [AllowNull] attribute

The next of the ideas is to make the property is annotated with the `[AllowNull]` attribute.

```csharp
// 👇 Add the [AllowNull] attribute
[Inject, AllowNull]
public IJSRuntime JS { get; set; }
```

This solution almost works well ― except the property is acceptable to the null even it is a non-nullable type.

```csharp
// 👇 There is no compiler error even if set to null.😥
this.JS = null;
```

## 3. Use "#pragma waning disable"

The last of the ideas is to make the property is surrounded by the "warning disable" pragma.

```csharp
// 👇 Surround the property by the "warning disable" pragma
#pragma warning disable CS8618 
    [Inject]
    public IJSRuntime JS { get; set; }
#pragma warning restore CS8618 
```

This solution also works fine. 
And, I think this solution is reflected what the developer wants to do most directly.

But this solution breaks the indent of the C# code, and the description volume is a little bit much, so the code loses readability.

Due to this, I do not prefer this solution.

## 4. [May 2, 2021, Updated] Use a `null` value with the `!` symbol to initialize the property

I did not know until I heard that, but we can initialize the non-nullable reference type variable by null value with the `!` symbol, like this: 

```csharp
[Inject]
public IJSRuntime JS { get; set; } = null!;
                                 //  👆 "null" with the "!" symbol
                                 //     can be set to non-nullable
                                 //     reference type property.
```

This implementation suppresses the CS8618 warning because the property is **initialized**, even the initial value is null.

And in my understanding, this solution doesn't have more side-effects any non-desirable.

So this solution became my best favorite solution.

# Conclusion

In my job and hobby, I often use the first solution out of the above 3.
But I am significantly dissatisfied with every solution above because those are not smart.

I hope a near future C# compiler and syntax resolve this annoying problem smartly.

_**[May 2, 2021, Updated]** As I said before, using the `null` value with the `!` symbol to initialize the property became my best solution at this time._

Actually, I use another solution too. That is, I don't mix it.
This means I use code-behind style, but I write the "@inject" directive in .razor files, do not write the properties that will be injected from DI container in .cs files, like this code:

```html
<!-- This is MyComponent.razor file -->

<!-- 👇 Inject the service in .razor file ... -->
@inject IJSRuntime JS
```

```csharp
// This is MyComponent.razor.cs file
public partial class MyComponent {
  ...
  // ... and use it in code-behind C# file.
  await this.JS.InvokeVoidAsync("foo");
```


If somebody knows a good solution for this problem, I appreciate it if you let me know via comment on this post.

Happy coding! :)