2016-05-26 3 views
2

したがって、私はreading an article at the momentであり、私はそれに質問する原因となったいくつかのコードに出くわしました。プロパティでnull-coalescing演算子を取得する

コードは次のようになります。私には

private UserService _userService = null; 

protected UserService UserService 
{ 
    get { return _userService ?? Request.GetOwinContext().GetUserManager<UserService>(); } 
} 

、それは私有財産は常にnullになりますように見えますので、ヌル・合体演算子を使用することは無意味です。 私はそれがこれを行うなどとして有用であると想像します:

protected UserService UserService 
{ 
    get { return Request.GetOwinContext().GetUserManager<UserService>(); } 
} 

私は何かが足りないのですか?そして、我々は、被写体にありながら、なぜこのん:

private UserService _userService = null; 

確かにそれは

private UserService _userService; 

と同じであり、私は私の疑念を明確に助けてください:D

+1

「get {return _userService ??」と書くのが一般的なパターンです。 _userService = Request.GetOwinContext()。GetUserManager (); } '。おそらくそれはタイプミスでしたか? – Rob

+0

おそらくアイデアは、ユーザーがコードのどこかに '_userService'を設定させ、もし彼がアイデンティティからそれを取得していなければ、その値を返したのかどうかということです。 'GetUserManager ()'はコンテキストごとに同じオブジェクトを返す可能性もあります。サービスインスタンスは常に同じで、フィールドに格納する特別な理由はありません。 – Fabjan

+0

それを保存する理由がない場合は、私の提案した解決策(コンテキストから戻す)が正しいのではないでしょうか? – r3plica

答えて

0

私はここに私の2セントを追加したい:

一つの可能​​性のある理由は、それがユーザー(DIコンテナ)によって割り当てられた場合_userServiceフィールドの値を使用していますreadonlyプロパティを作成したいという開発者(複数可)だけであり、場合単にIdentity値プロバイダからの戻り値ではありませんでした(このプロバイダは、httpコンテキストごとにシングルトンを使用する可能性が高いです)。

一般的に言えば、この唯一の目的のためsetterが存在するので、フィールドの値をgetterプロパティの中に割り当てるという考え方は嫌です。我々はコンストラクタでこのフィールドを設定し、それにオプションのパラメータを追加することができ、「通常の方法で、」それをより作るためのコードで何かを変更したいと仮定すると

private UserService _userService; 

protected UserService UserService 
{ 
    get 
    { 
     return _userService; 
    } 
} 

public MyController(UserService service = null) 
{ 
    this._userService = service ?? 
      Request.GetOwinContext().GetUserManager<UserService>(); 
} 

今のコードがされますよりテスト可能で素敵です。 DIフレームワークを使用することもできます。このアプローチの唯一の欠点は、遅延ロードから離脱したことです。まあ、我々はLazy<T>で再びそれを使用することができます:

private Lazy<UserService> _userService; 

protected UserService UserService 
{ 
    get 
    { 
     return _userService.Value; 
    } 
} 

public MyController(UserService service = null) 
{ 
    service = service ?? 
      Request.GetOwinContext().GetUserManager<UserService>(); 

    _userService = new Lazy<UserService>(service); 
} 

は、今では私たちのコードをテスト装置に容易になり、私たちはDIフレームワークを使用して遅延ロードを使用して恩恵を受けることができます。

P.S.

nullの値は、参照フィールドのフィールドに明示的に割り当てられても意味をなさない。私が考えることができる唯一の理由は、読みやすさを少し向上させることですが、これは完全に意見に基づいているようです。

4

そうですね、プライベートプロパティは、あなたの例では常にnullになります。それを解決するために

一つの方法として、このコードを使用している:

private UserService _userService = null; 

protected UserService UserService 
{ 
    get 
    { 
     return _userService ?? (_userService = Request.GetOwinContext().GetUserManager<UserService>()); 
    } 
} 

この道をプライベートプロパティがnullでないときに使用され、または割り当てられた値に初期化されます。ヌル合体オペレータ??の後のステートメントが実行されると、実際には_userServiceに割り当てられた値が返されます。

+0

@CarbineCoderどのようなエラーメッセージが表示されますか?これは実際にコンパイルする必要があります。なぜなら、 '??' _userServiceを返します。 –

+0

@CarbineCoderすべてはここで正しいです。代入演算はC#で代入された値を返します(おそらく、この動作は一部の言語では異なります)。 –

+0

私の悪い...申し訳ありませんが、私は括弧を逃した。 – CarbineCoder

1

それはそのアプローチを持つことは珍しいことではありませんが、通常それはのようなパラメータ化コンストラクタが付属しています:

public class X 
{ 
    private UserService _userService = null; 

    protected UserService UserService 
    { 
     get { return _userService ?? Request.GetOwinContext().GetUserManager<UserService>(); } 
    } 


    public X() { } 

    public X(UserService svc) { _userService = svc; } 

またはメソッドと同様に、サービスメソッドを移入するいくつかの他の方法:

public void SetUserService(UserService svc) { _userSErvice = svc; } 

これを行うメリットは、MoqやRhino.Mocksのようなモックフレームワークを使って虚偽のUserServiceサービスで構築できることです。

+0

しかし、パラメータ化されたコンストラクタがない場合は、それは役に立たないのですか? – r3plica

+0

ええと@Hermanは、ソリューションが動作すると言うか、コンストラクタでその解決策を実行します(変数を初期化します)。 –

関連する問題