Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nullable Enable and Generics default #3471

Closed
HavenDV opened this issue May 20, 2020 · 10 comments
Closed

Nullable Enable and Generics default #3471

HavenDV opened this issue May 20, 2020 · 10 comments

Comments

@HavenDV
Copy link

HavenDV commented May 20, 2020

After adding <Nullable>enable</Nullable> or #nullable enable, I ran into the following problem with my Generic methods:

This does not work:

public T? GetDefault<T>()
{
    return default;
}

enter image description here

This works with warning:

public T GetDefault<T>()
{
   return default;
}

enter image description here

This works individually, but not together.

public T? GetDefault<T>() where T : class
{
    return default;
}

public T? GetDefault<T>() where T : struct
{
    return default;
}

enter image description here

Logically, the first method should work.
What is the correct way out of this situation without creating several methods and suppressing warning?

P.S.
At the moment, I have not found anything better than this solution:

public T GetDefault<T>()
{
    return default!;
}

public void OtherMethod()
{
    string value1 = GetDefault<string>();
    string value2 = GetDefault<string?>();
    string? value3 = GetDefault<string?>();
}

enter image description here

@bbarry
Copy link
Contributor

bbarry commented May 20, 2020

agree it is frustrating; not much to do about it I think now though.

Here is what I do:

[return: MaybeNull]
public T GetDefault<T>() => default!;

public void OtherMethod()
{
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
    string value1 = GetDefault<string>();
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
    string? value2 = GetDefault<string?>();
    string? value3 = GetDefault<string>();
}

@333fred
Copy link
Member

333fred commented May 20, 2020

C# 9 will bring T??: #3297.

Until then, you can use @bbarry's solution. Note that the pragma warning suppressions would only be needed if you attempted to assign a string? to a string, as is done on the first line of OtherMethod there.

@333fred
Copy link
Member

333fred commented May 20, 2020

You can see the full set of attributes that can inform nullable analysis here: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/nullable-analysis.

@HavenDV
Copy link
Author

HavenDV commented May 20, 2020

The interesting thing - Visual Studio offers this edit:
image

@CyrusNajmabadi
Copy link
Member

Tagging @jcouv for VS issue above.

@HavenDV
Copy link
Author

HavenDV commented May 21, 2020

Is there a way to use the [MaybeNull] attribute in a .Net Standard 2.0 project?

@bbarry
Copy link
Contributor

bbarry commented May 21, 2020

I think you might be able to declare the attributes as internal in the correct namespace within your assembly? I haven't tried because targeting .Net standard leaves too many warts for me to deal with so I gave up and multitarget just net48 and netcoreapp3.1. Hopefully net5/6+ will improve things and let me gain mono/uwp/xamarin/etc. runtime support before I actually need them.

dotnet/runtime#29617 (comment)

@HavenDV
Copy link
Author

HavenDV commented May 21, 2020

What about the situation where I need to deliver a nuget package that contains a public function with this attribute?

@bbarry
Copy link
Contributor

bbarry commented May 21, 2020

The compiler is looking for an attribute on the type with the full name (no assembly though) of System.Diagnostics.CodeAnalysis.MaybeNullAttribute.

It isn't looking for a specific type.

This is similar to how async works in earlier versions of .net framework. The internal attribute would have the same name.

@YairHalberstadt
Copy link
Contributor

The original example is now legal in C# 9

public T? GetDefault<T>()
{
    return default;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants