2016-09-23 5 views
2

は(私はそれが働くように見えることはできませんので、場合瞬間のために制約をの前述...)次の操作を実行することが可能です定義が含まれていません...「T」は

入力した場合は(理由それは推論されている)、何が問題なのですか?上記のコードでは

private void GetGenericTableContent<T>(ref StringBuilder outputTableContent, T item) 
{ 
    outputTableContent.Append("<td>" + item.SpreadsheetLineNumbers + "</td>"); 
} 

// 'item' is either DuplicateSpreadsheetRowModel class or SpreadsheetRowModel class 

私は次のエラーを取得する:

'T' does not contain a definition for 'SpreadsheetLineNumbers' and no extension method 'SpreadsheetLineNumbers' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)

+0

現在、Tがオブジェクト型で、オブジェクト 'に' SpreadsheetLineNumbers 'の定義が含まれていないため、ジェネリックメソッドに制約を追加する必要があります。 DuplicateSpreadsheetRowModelクラスまたはSpreadsheetRowModelが共通の基底クラスの実装から派生している場合、同じインターフェイスではそれを制約として使用します。 – 3615

+0

C#のジェネリックは暗黙的に型指定されていません。あなたのメソッドの署名が書かれている方法では、 'GetGenericTableContent(someStringBuilder、42)'と 'T = int'を呼び出して呼び出すことができます。明らかに、これは 'int'にメンバ' SpreadsheetLineNumbers'がないのでC#があなたのコードを正しく拒否するので失敗します。それが制約の全ポイントです。 –

+0

ああ、誤って、コンパイル時に推論された型を除外することによって、MSが "コンパイラは渡すメソッドの引数に基づいて型パラメータを推論することができます。制約または戻り値。 "コンパイラには、型推論が成功した汎用メソッドのみが含まれています。" ...だから私はどのタイプが成功するのだろうと思っています...うーん...うまくいけば、私は制約を追加します。 –

答えて

7

いいえ、それは不可能です。一般的な型はコンパイル時に知られていなければなりません。 考えてみてください。TにはSpreadsheetLineNumbersのプロパティがあることがコンパイラによってどのように保証されていますか? Tintまたはobjectの場合はどうなりますか?

ref stringBuilder, 999パラメータでメソッドを呼び出すことを妨げる原因はありますか?だから、

それはあなたがこのプロパティとインタフェースを追加した場合のみ動作したい:このインタフェースからクラスを継承し

public interface MyInterface 
{ 
    string SpreadsheetLineNumbers { get; set; } 
} 

とlet

public class MyClass : MyInterface 
{ 
    public string SpreadsheetLineNumbers { get; set; } 
} 

次に、コンパイラは、このことを知っているように、一般的な制約を使用型はこのインタフェースから継承されているため、はすべてのプロパティを含むに属していなければなりません。

private void GetGenericTableContent<T>(ref StringBuilder outputTableContent, T item) 
    where T : IMyInterface // lets compiler know that T type has implemented all members of the interface 
{ 
    outputTableContent.Append("<td>" + item.SpreadsheetLineNumbers + "</td>"); 
} 
4

あなたがあなたのタイプのためのインターフェイス(またはいくつかのタイプの間で一般的なもの)を作成できない場合:

private void GetGenericTableContant<T>(ref StringBuilder outputTableContent, T item, Func<T, string> lineNumberAccessor) 
{ 
    outputTableContent.Append("<td>" + lineNumberAccessor(item) + "</td>"); 
} 

使用法:

GetGenericTableContent(ref outputTableContent, item, x => x.SpreadsheetLineNumbers); 

(または、あなたは可能性があなたのメソッドにアイテム参照が本当に必要ない場合は、SpreadSheetLineNumbersプロパティを渡してください:void GetGenericTableContant<T>(ref StringBuilder outputTableContent, string lineNumbers)

関連する問題