2017-08-02 6 views
1

私はC#が新しく、テンプレートタイプに分散制限を適用しようとするといくつかの実際の問題があります。たぶん私の研究で見つけることができる唯一の "どこ"句の例は、他の方向に行くことにより基づいているのかもしれません(つまり、 "割り当てることができます")。私はエミュレートしようとしているScala関数を列挙しました - その点はTがUに代入可能であることを保証することです(つまりT <:U)。戻り値は何であれUであるためです。任意のヘルプまたはC#の分散についてのヒントは、ScalaのオプションからあなたにC#分散リターンタイプ

interface Option<out T> // where T : class 
    { 
     T GetUnsafe(); 
     Option<X> map<X>(Func<object,Option<X>> f); 
     U GetOrElse<U>(U u) where T:U ; //What is wrong here,how do I get U:>T ? 

     bool IsSome { get; } 
    } 

例に感謝し、高く評価され、[A] 最終DEF getOrElse [B>:A](デフォルト:⇒のB):B

として、更新は、ここでは静的関数として働いたバージョンだ - それはあなたが「ジェネリック型制約」と「一般的な差異を」混ぜるように見える方法

static class Option 
    { 
     public static U GetOrElse<T, U>(Option<T> o, U defAns) where T : U 
     { 
      if (o.IsSome) return o.GetUnsafe(); else return defAns; 
     } 
+1

これが機能するには、メソッドの代わりにインタフェースで 'U'を宣言する必要があります。 – juharr

+0

前述のように、分散はインターフェイスのタイプパラメータでのみ機能します。とにかく、メソッドに必要な制約は有効ではありません(クラスの一部を継承するメソッドの型パラメーターのみを制約できます)。それは、IMHOそれはそのような方法を持つのは厄介なデザインだと言った。なぜメソッドが 'T'を返すことができないのですか? 'Option 'を持っている人にとって、 'GetorElse ()'という型パラメータを 'T 'の基本型にするだけでいいのですか?あなたの質問は、[XY問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)に非常によく似ています。 –

+0

@PeterDuniho私はこれが奇妙に見えるかもしれないが、私の発明ではないことを知っています。ここでは、Uがこのように限定されている必要がある理由の例を示します。これはオブジェクトであると言われています。ですが、内部コードがないのに、オプションを扱うコードにアップキャストされています。その瞬間に呼び出すコールは、Uがそのアイテムのスーパータイプであることを保証する必要があります。そうしないと、完全に間違ってしまうでしょう。 Var Cat = myCat.getOrElse(123455)は問題になります。 – LaloInDublin

答えて

1

まず第一として可能だ場合、私はちょうど把握することはできません。はい、C#はJavaと異なり、スカラは継承関連の型制約を一方向にしかサポートしていません:基本クラスを指定できます(しかし、スカラもJavaサポートもnew制約のようなことはできません)。詳細については、where (generic type constraint) (C# Reference)を参照してください。 Tが外側のスコープで定義されているので、内側のスコープに追加の制約を置くことはできません。これがあなたの例がコンパイルされない理由です。 C#コンパイラは宣言のジェネリック型を並べ替えるだけで、既に知られている型(U)を使用してconstraint(T)を定義するように見えるので、静的メソッドを使用する2番目の例はコンパイルされます。

私はあなたがタイプBの値を取得したい場合Optionはその実際の型は自分varを宣言Aであっても共変すなわちであるという事実与えられたgetOrElse Scalaの方法と設計の実際の生活の使い方がわからないんだけどタイプはOption[B]です。だから私は、このビットのロジックをコピーしないことは大きな損失ではないと思います。

一般的に私は、ScalaからC#に動作を正確に保持するコードを簡単にコピーすることはできないと思いますが、このメソッドがオーバーライドする必要のない固定実装が1つしかないこの特定のケースでは、

public static class OptionHelper 
{ 
    public static U GetOrElse<T, U>(this Option<T> o, U defAns) 
     where T : U 
    { 
     if (o.IsSome) return o.GetUnsafe(); else return defAns; 
    } 
} 

ための追加thisキーワードのそれはインタフェース自体に定義されていたかのようにあなたが(ビットのJava 8のデフォルトの方法に類似して何を暗黙的に使用して取得することができ、それを使用することができ、引数の前に:extension methodsを使用するには、静的なトリックScalaのコンバージョン):

Option<string> o = ..; 
object value = o.GetOrElse(new object()); 
+0

ありがとう、静的関数は、これらの問題を回避する最善の方法と思われる – LaloInDublin