ORMでDTOクラスを使用する場合のC#8のnull可能な参照型


9

以下に示すように、データ転送オブジェクト(DTO)クラスを持つプロジェクトでこの機能をアクティブにしました。

public class Connection
    {
        public string ServiceUrl { get; set; }
        public string? UserName { get; set; }
        public string? Password { get; set; }
        //... others 
    }

しかし、私はエラーを受け取ります:

CS8618:null可能ではないプロパティ 'ServiceUrl'は初期化されていません。プロパティをnull許容として宣言することを検討してください。

これはDTOクラスなので、プロパティを初期化していません。これは、プロパティがnullでないことを保証するためにクラスを初期化するコードの責任です。

たとえば、呼び出し元は次のことができます。

var connection = new Connection
{
  ServiceUrl=some_value,
  //...
}

私の質問:C#8のnull可能性コンテキストが有効になっているときに、DTOクラスでこのようなエラーを処理する方法は?


3
示されている方法で構築の初期化を行うと、デフォルトのコンストラクターが実行されます(ServiceUrlをデフォルト値(文字列の場合はnull)に初期化します)。次に、initializeステートメントが実行されます。null不可にしたい場合は、初期化されたすべてのコンストラクターを終了する必要があります
Flydog57

POCOは、コンストラクターがないことや、プロパティが初期化されていないことを意味しません。という意味Plain Old C# Objectです。特別なクラスから継承することなく、他のオブジェクトと同様のオブジェクト。別の質問がある思います。DTOの作成方法Data Transfer Objects
Panagiotis Kanavos

This should be the responsibility of the one initializing the class to ensure that the properties are non-nullクラスは常に有効な状態でなければなりません。nullが許可されていない場合、プロパティをnullにすることはできません。おそらく、基本的な文字列の代わりに、NoneF#のOptionクラスのように、or`Missing`の値を持つことができるURLの特殊なクラスを使用する必要があります。C#8を使用すると、そのようなクラスを記述して、パターンマッチングでチェックすることができます
Panagiotis Kanavos

@Panagiotis Kanavos、私の場合、クラスにはパラメーターのないコンストラクターであるという制約があります。したがって、プロパティ初期化子を使用する必要がありますpublic string ServiceUrl { get; set; } = default! ;。Roslynがctorのスコープ外で遅延初期化を処理する方法を将来的に持っていることを願っています。私はMayBe <T>(Optionクラスと同様)を使用していましたが、新しいコードのためにc#8でnull可能な参照型に切り替えました。
M.Hassan

NRTはMaybesではありません。実際、Maybesはさらに重要で使いやすくなりました。もちろん、それらはパターンマッチングでの作業を容易にするC#イディオムを使用してビルドされています
Panagiotis Kanavos

回答:


9

次のソリューションはEF CoreとEF6で推奨されています 参照してください

1)を null!寛容な演算子で

public string ServiceUrl { get; set; } = null! ;
//or
public string ServiceUrl { get; set; } = default! ;

2)バッキングフィールドの使用:

        private string _ServiceUrl;
        public string ServiceUrl
        {
            set => _ServiceUrl = value;
            get => _ServiceUrl
                   ?? throw new InvalidOperationException("Uninitialized property: " + nameof(ServiceUrl));
        }


質問では、!オペレーターを使用できないと述べました。
Athanasios Kataras

使えない!タイプを使用しますが、私が言及したリンクはnullを使用して初期化する方法を示しています。これは回避策のソリューションです。質問を修正しました。
M.Hassan

8

null可能ではない場合、オブジェクトが初期化されるときにコンパイラーは何ができますか?

文字列のデフォルト値はnullなので、

  1. 宣言で文字列のデフォルト値を割り当てる必要があるか

    public string ServiceUrl { get; set; } = String.Empty;

  2. または、デフォルトのコンストラクタの値を初期化して、警告を解消します

  3. !演算子を使用する(使用できない)

  4. robbpriestleyが述べたように、それをヌル可能にします。


4
または、サービスURLをnull不可の文字列として受け入れるコンストラクタを追加します。
Jon Skeet、

ServiceUrl'= String.Emptyにすることはできません。nullにできない複合型の他のプロパティがあるため、次のように使用しましたdefault: 'public MyClass MyProperty {get; セットする; } =デフォルト!'警告を停止します。このクラス(およびその他)はパラメーターのないコンストラクターであり、最近ではctorのスコープ外で初期化されています。
M.Hassan

0

いくつかのシナリオで役立つかもしれないもう一つ:

[SuppressMessage("Compiler", "CS8618")]

メンバーまたはタイプ全体の上に使用できます。


考慮すべきさらにもう1つのことは#nullable disable、ファイル全体にnullを指定できる参照を無効にするためにファイルの上に追加することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.