1

これら2つの違いは何ですか、そして「正しい」ものは何ですか?

public interface IMessage
{
    /// <summary>
    /// Array used to hold all bytes that will be written.
    /// </summary>
    IList Buffer { get; set; }
}

public interface IMessage<T> where T : IList
{
    /// <summary>
    /// Array used to hold all bytes that will be written.
    /// </summary>
    T Buffer { get; set; }
}

編集1:修正済み-インターフェースにフィールドを含めることはできません。(BoltClockに感謝)
編集2:修正済み-インターフェイスにカプセル化を設定できません。(KeithSに感謝)

4

3 に答える 3

5

どちらも概念的には「正しい」ものであり、意味的にはほぼ同じことを意味します(構文エラーを気にしない場合、インターフェイスはフィールドを持つことができないため、プロパティとして定義されていれば問題ありません)。

IList汎用バージョンでは、 -以外のタイプを返すListことができるため、インターフェイスタイプの代わりにaを返すことができます。

于 2012-07-23T19:12:22.600 に答える
0

私の記憶が正しければ、2番目のバリアントでは、IListから独自のクラスをTとして使用できます。

于 2012-07-23T19:17:42.607 に答える
0

最初のケースでは、バッファはタイプIListであると定義されています。実行時に、IListの任意の実装を割り当てることができ、このインターフェースの実装の作成者は、使用される実装を正確に知る必要はありません。ただし、コードは実行時にどの正確な具象実装が使用されているかを知ることができないため、設計時にこのプロパティをインターフェイスのメンバーとして参照する場合、IListインターフェイスによって明示的に公開されていないメソッドにアクセスすることはできません。

2番目のケースでは、ジェネリックを定義しています。この一般的な定義が「オープン」のままである(Tが定義されていない)場合でも、IListのメソッドの使用に制限されます。ただし、インターフェイスの実装またはジェネリックを開いたままにする実装の特定のインスタンスの定義のいずれかで、このジェネリックを閉じる必要があります。ジェネリックが閉じられると、正確で具体的なタイプのバッファーわかり、IListで必ずしも定義されていないメソッドを呼び出すことができます。ただし、ジェネリックが閉じられると、特定のジェネリック型を定義するインスタンスまたはクラスに、バッファーとして使用するIListの別の実装を与えることはできません。

したがって、いくつかの例(インターフェイスで指定できない保護されたフィールドが実際には変更可能なパブリックプロパティであると想定):

//this class implements the non-generic interface, so buffer is an IList.
class MyMessage1: IMessage
{
   public IList buffer {get;set;}

   public MyMessage1()
   {
      buffer = new List<string>();

      //even though you "know" what you just assigned, 
      //you cannot refer to buffer as a List<string>, even here.
      buffer.Sort(); //error
   }
}

...

//The exact type of buffer cannot be known statically, 
//so only non-generic IList methods are allowed
var myMessage = new MyMessage1();
myMessage.buffer.Add("my message"); //valid; string literals are Objects
var firstLen = myMessage.buffer[0].Length; //error: indexer returns Objects.
myMessage.Sort(); //error: IList does not have a Sort() method.
firstLen = GetFirstLength(myMessage); //error: not an IMessage<List<string>>
//but, an IList is an IList no matter what, so this works.
myMessage.buffer = new List<int>(); 

...

//this class keeps the generic open so T can be any IList, determined at instantiation.
class MyMessage2<T>:IMessage<T> where T:IList
{
    public T buffer {get;set;}

    //buffer's exact type is still not known here,
    //so inside this class you are still restricted to IList members only
    public int BufferCount{get{return buffer.Count;}}

    public void SortBuffer()
    {
       buffer.Sort(); //error; no such method
    }    
}

...

//but, once you define an instance, you know exactly what buffer is
var myMessage = new MyMessage2<List<string>>();
myMessage.buffer.Add("my message");
var firstLen = myMessage.buffer[0].Length; //now we know the indexer produces strings.
myMessage.buffer.Sort(); //buffer is known to be a List<T> which has Sort()
firstLen = GetFirstLength(myMessage);

...

//and when you pass it as a parameter, you can close the generic of the interface
public string GetFirstLength(IMessage<List<string>> message) 
{
   //...so you still know what you're dealing with
   return message.buffer[0].Length;
}

...

//however, buffer is now "strongly typed" and the implementation can't change
myMessage.buffer = new List<int>(); //error; buffer is of type List<string>

...

//this class closes the generic within the declaration.
class MyMessage3:IMessage<IList<string>>
{
   //now we're closing the generic in the implementation itself,
   //so internally we know exactly what we're dealing with
   public List<string> buffer {get;set;}

   //...so this call is valid
   public void SortBuffer() { buffer.Sort(); }
}

//...and consuming code doesn't have to (get to?) specify the implementation of T
var myMessage = new MyMessage3();
//... but still knows exactly what that implementation is
myMessage.buffer.Add("my message");
var firstLen = myMessage.buffer[0].Length;
myMessage.buffer.Sort();

//and btw, MyMessage3 is still an IMessage<List<string>>
firstLen = GetFirstLength(myMessage);

//... and buffer's still a strongly-typed List<string>
myMessage.buffer = new List<int>(); //error
于 2012-07-23T19:18:32.603 に答える