0

I want to know if a property type is a nullable reference type or not. I found several blog posts claiming that we can simply check the custom attributes by reflection. Given the class Foo:

public class Foo 
{
    public string Bar1 { get; set; }
    public string? Bar2 { get; set; }
}

I make the following calls:

typeof(Foo).GetProperty("Bar1").CustomAttributes //returns an empty collection
typeof(Foo).GetProperty("Bar2").CustomAttributes //returns a collection with one instance of NullableAttribute

Weirdly, when I change the class to:

public class Foo 
{
    public string? Bar2 { get; set; }
}

Now, the CustomAttributes are empty.

typeof(Foo).GetProperty("Bar2").CustomAttributes //returns an empty collection

What is a reliable way to determine if a property type is a nullable reference?

user2900970
  • 751
  • 1
  • 5
  • 24
  • You could check if it is a `Nullable` and then if the generic argument is a reference type. – Jeroen van Langen Mar 16 '20 at 13:20
  • 1
    @JeroenvanLangen `Nullable` is struct and value type, not the reference one – Pavel Anikhouski Mar 16 '20 at 13:21
  • The `CustomAttributes` collection should contain a series of elements that all inheirt `System.Attribute`, but those elements should have more specific classes that you can check with `x.GetType()` and I believe there is an overload `GetCustomAttribute()` that lets you get a specific one. There should be a specific attribute that is used for nullable in C#8 although I don't know what it is. If you look for _any_ attribute, you may run into errors with your current method, because attributes are used in many contexts. – JamesFaix Mar 16 '20 at 13:24
  • Accroding to [sharplab.io](https://sharplab.io/#v2:CYLg1APgAgTAjAWAFBQMwAJboGIHtfICQA3kYQPTlqZwAM6AQgIYBOc6x6A5gKYAuAbnQBnfkIC+ZalDoB+RqxgduYkaslJC4oA=) for first case attribute is applied to nullable property, for second one - to `Foo` class itself (because it contains only nullable types, I guess). So, you should check the both cases and can also have a look at [nullable metadata](https://github.com/dotnet/roslyn/blob/master/docs/features/nullable-metadata.md) document. The attached duplicate has an essential answer how to do that properly – Pavel Anikhouski Mar 16 '20 at 13:26
  • You need to check the entire tree *above* this - the declaring type, module, assembly, etc; it is in/out/in/out – Marc Gravell Mar 16 '20 at 13:47
  • @PavelAnikhouski It will wrap the original type. `int?` is actually `Nullable` – Jeroen van Langen Mar 16 '20 at 13:55
  • @JeroenvanLangen nullable value types and nullable reference types are different things, first ones is a separate type, `Nullable`, they wrap original type. Nullable reference types added in C# 8and are implemented using type annotations, they doesn't wrap anything – Pavel Anikhouski Mar 16 '20 at 14:04

0 Answers0