C # nullable referanslarını bir yöntemin etkili bir şekilde boş bir denetim olduğunu söyleyebilir miyim


14

Aşağıdaki kodu göz önünde bulundurun:

#nullable enable
class Foo
{
    public string? Name { get; set; }
    public bool HasName => Name != null;
    public void NameToUpperCase()
    {
        if (HasName)
        {
            Name = Name.ToUpper();
        }
    }
}

Name = Name.ToUpper () üzerinde adı açıkça yanlış olan olası bir boş başvuru olduğuna dair bir uyarı alıyorum. HasName'i satır içine alarak bu uyarıyı iyileştirebilirim, böylece durum (Name! = Null).

Derleyiciye HasName'den gelen gerçek bir yanıtın Ad üzerinde bir kuralsızlık kısıtlaması gerektirdiğini söyleyebilmemin bir yolu var mı?

Bu önemlidir çünkü HasName aslında çok daha fazla şeyi test edebilir ve bunu birkaç yerde kullanmak isteyebilirim veya API yüzeyinin herkese açık bir parçası olabilir. Null kontrolü kendi yöntemine dahil etmek için birçok neden vardır, ancak bunu yapmak null edilebilir referans denetleyicisini bozuyor gibi görünmektedir.


1
IMO'yu HasValuenullable tipinde kullanmanız gerekir null; Muhtemelen sorununuzu etkilemez.
fredrik

Sanırım sizin için, #nullable disabledaha sonra #nullable enableveya restoredaha sonra kodunuzu sarabilirsiniz ( docs.microsoft.com/en-us/dotnet/csharp/… ).
19:10, GaryNg

5
"dammit" !operatörünü kullanabilirsiniz. if(HasName) { Name = Name!.ToUpper(); }
Jan Paolo Go

1
çok iş parçacıklı bir uygulama için, özelliğe geri dönmek yerine değişkeni yerel olarak kullanarak HasName denetiminden sonra Ad'ın boş olmasını sağlayabilirsiniz (mülkün alıcısında neler yapabileceğini bilen) bazı korkak hatalar verecektir (unutmayın bunun çok olduğu bir olay işleyicisinin kullanımı)
XIU

Yanıtlar:


3

Etraftaki farklı özelliklere baktım System.Diagnostics.CodeAnalysisve çok hayal kırıklığı yaratan uygulanabilir bir şey bulamadım. İstediğinize en yakın şey şu şekilde görünür:

public bool TryGetName([NotNullWhen(true)] out string? name)
{
    name = Name;
    return name != null;
}

public void NameToUpperCase()
{
    if (TryGetName(out var name))
    {
        Name = name.ToUpper();
    }
}

Çok hantal görünüyor, biliyorum. Null olabilecek özellikler için MSDN belgelerine bakabilirsiniz , belki daha düzgün bir şey bulabilirsiniz.


2
Daha fazla özelliğe ihtiyacımız var gibi görünüyor ya da
yazı tipinin

Bunu cevap olarak seçeceğim, çünkü gerçek cevabın, korktuğum gibi, "hayır, c # henüz yapmıyor" gibi görünüyor.
John Melville

@JohnMelville Ben de böyle bir özellik için bir teklif bulamadım, bu yüzden yakında bu değişmeyi bekleyebilirsiniz sanmıyorum.
V0ldek

2
@XIU Derleyici bu açıdan zaten gevşek. Eğer yaparsanız if(Name != null) return Null.ToUpper(), teknik olarak bir TOCTOU yarış koşulu olmasına rağmen, boş bir dereference için uyarı olmayacaktır. Mads Torgersen'in bunu nasıl düşündükleri hakkında konuştuğunu hatırlıyorum, ancak bu kadar çok yanlış pozitif üretecek tüm nullable referans türleri özelliği etkili bir şekilde işe yaramaz - özelliklerinizin% 99'u başka bir iş parçacığı tarafından değiştirilmez. Tek yapmanız gereken, bu mülk üzerindeki çekin başka bir mülkte null olup olmadığını kontrol etmesini sağlayacak bir özellik yapmaktır.
V0ldek

2
"Bunun için bir teklif bulamıyorum" sorununu çözdüm. ( github.com/dotnet/csharplang/issues/2997 ) Bana şans dileyin .
John Melville

-10

Dize bir başvuru türüdür ve nullable (örn. int?) Nullable değer türleridir. Yani bunu gerçekten yapamazsınız string? myString; İhtiyacınız olan şey:

class Foo
{
    public string Name { get; set; }
    public bool HasName => !String.IsNullOrEmpty(Name);  ////assume you want empty to be treated same way as null
    public void NameToUpperCase()
    {
        if (HasName)
        {
            Name = Name.ToUpper();
        }
    }
}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.