2011-01-21 3 views
1

私は関数のリストを作成しようとしていますが、苦労しています。ここに簡略化したバージョンがあります:制限付きTsのFunc <T, string>をその制約付きタイプを使用するコレクションに追加する方法

public class ValueGetter 
{ 
    public List<Func<Control, string>> Operations { get; set; } 

    public ValueGetter() 
    { 
     this.Operations = new List<Func<Control, string>>(); 
    } 

    public void Map<T>(Func<T, string> valueGetter) where T : Control 
    { 
     this.Operations.Add(valueGetter); 
    }   
} 

この機能をコレクションに追加しようとすると問題が発生します。私はこれを行うことができますが、これはTがコントロールであるために必要ですが、これはコンパイルされません。

このコレクションに機能を追加する方法はありますか?

答えて

1

これはできません。

TControlであるが、すべてがTではない。
Func<TextBox, bool>をリストに追加した後、それをButtonとして(Func<Control, string>として)呼び出すとどうなりますか?

あなたはすべての可能なTControlあるので、Func<T, string> where T : Control>Func<Control, string>をキャストするcovarianceを使用することができます。

+0

ありがとうございます、私はFuncが他のタイプのコントロールでは機能しないことを忘れていました。 – Liath

+0

@Liath:本当にここで必要なのは、「Control:T」という制約です。つまり、TはControlまたは任意の基本タイプのコントロールです。それは型安全です。残念ながら、C#はこの種の制約をサポートしていません。あなたがその種の制約を表すことができる言語を探しているなら、Scalaを試してみてください。私は彼らがそれをすることができると思う。 –

1

あなたはジェネリックとしてクラスを宣言shoud:

public class ValueGetter<T> where T : Control 
{ 
    public List<Func<T, string>> Operations { get; set; } 

    public ValueGetter() 
    { 
     this.Operations = new List<Func<T, string>>(); 
    } 

    public void Map(Func<T, string> valueGetter) 
    { 
     this.Operations.Add(valueGetter); 
    }   
} 
1

あなたが持って終わるだろうので、これは、例えば、リスト内のFunc<Button, string>を動作しないだろうが、あなたがそれを呼び出してしまう可能性があり、たとえば、Labelとなります。 Buttonが、Labelと関係すると予想される関数は何ですか?換言すれば、

public class ValueGetter<T> where T : Control 
{ 
    public List<Func<T, string>> Operations { get; set; } 

    public ValueGetter() 
    { 
     this.Operations = new List<Func<T, string>>(); 
    } 

    public void Map(Func<T, string> valueGetter) 
    { 
     this.Operations.Add(valueGetter); 
    } 
} 

各コントロールタイプに別々のValueGetter秒を持っている:

あなたはこのような何かを行うことができます。

編集:もう一つのアイデア:あなたは、単にタイプは、例えば、右である場合にのみ操作できる機能を追加できます。Button -expecting機能が指定されている場合は、この場合、

public void Map<T>(Func<T, string> valueGetter) where T : Control 
{ 
    this.Operations.Add(control => (control is T) ? valueGetter((T) control) : null); 
} 

Labelの場合、nullを返すだけです。

関連する問題