2011-01-27 13 views
0

私は、インタフェースの範囲を超えて、他のプログラマと紛争しています。基本的なC#インターフェイスのスコープとは何ですか?

は、我々は次のことを考えてみます。

public interface IFoo 
{ 
    string Bar { get; set; } 
} 

public class SomeFoo: IFoo 
{ 
    public string Bar { get; set; } 

    public SomeFoo(string bar) 
    { 
     this.Bar = bar; 
    } 
} 

public class Consumer 
{ 
    public void DoSomething() 
    { 
     SomeFoo fooClassInstance = new SomeFoo("test"); 
     IFoo fooInterface = (IFoo)fooClassInstance; 

     // do something with fooInterface. 
    } 
} 

そこで質問です: 1.それは何か他のものがfooInterfaceインスタンスを解放する前にfooClassInstanceがスコープの外に出ることは可能ですか?

オブジェクト(fooClassInstance)がスコープ外に出る可能性があると主張する人もいます。

私はそれが傾けると信じています。 GCがオブジェクトがスコープ内に存在しなくなったと判断した場合、オブジェクトはGCによって廃棄される場合もあれば、処理されない場合もあります。しかしながら、インタフェースは設計上、抽象的な契約であり、それを使用するオブジェクトによってメンバを実装する必要があります。インタフェースが使用されている限り、インタフェースは実装を失うことができません。まったく別のオブジェクトがタイプ "インタフェース"として作成されているようなものではありません。インタフェースは、単に実装者の抽象メンバへのポインタにすぎません。

この紛争を解決するお手伝いができますか?

おかげで、

<bleepzter /> 
+0

インターフェイスには実装がありません。したがって、インターフェイスを実装しているクラスは範囲外になります。インターフェイスは契約のようなものです。実装することはあなたが実装する予定のものなので、ガベージコレクトするものはありません。あなたの例では、元のオブジェクトへの参照を作成し、それをインターフェイスにキャストしています。これはCOMの古いIUnknown :: QueryInterfaceでした(しかし、現在は同じ概念です)。 – SRM

+1

あなたの例では、クラスインスタンスとインターフェイスインスタンスの両方が同時にスコープから外れます。 – Victor

+1

'fooClassInstance'を' IFoo'にキャストする必要はありません。すでに* IFooです。 –

答えて

1

「実装を失う」とはどういう意味ですか?それは意味をなさない。型はインタフェースを実装しますが、インタフェースを「実装しない」ことはできません。

あなたのコード例では、割り当てられたオブジェクトの存続期間は、もはやルートが存在しなくなった瞬間(つまり、GCによってもう到達できなくなった)に終わります。参照の型にかかわらず、参照は参照型です(つまり、参照型が派生型または親型の場合は問題ありません)。

ISomething Sample() { 
    Something s1 = new Something(); 
    s2.DoSomething(); // Assuming s is the only reference to s, then it no longer is 
         // rooted after this expression 

    Something s2 = new Something(); 
    ISomething is1 = s2; 
    s2 = null; 
    is1.DoSomething(); // The reference remains valid and the lifetime of the 
         // object created continues until we release all 
         // remaining references to it. 
    return is1; 
} 
+0

だから私は何かにインターフェイスを渡す場合、fooClassInstanceはどうなりますか?さらに、fooClassInstanceが破棄されている間に、渡された場合、インタフェースのBar文字列はどうなりますか? – bleepzter

+1

オブジェクトへの参照を保持していれば、引き続き有効です。派生型、親の型、オブジェクト、実装されたインタフェースなど、参照の型にかかわらず – Washu

+0

"オブジェクトが強く到達可能である限り..." ;-) –

2

私はあなたがインスタンス参照の間に線をmuddlingていると思います。 fooClassInstanceは、オブジェクトのインスタンスがまだ存在していても(fooInterfaceにはまだ参照が保持されているため)、範囲外になります(つまり、参照できなくなります)。

たとえば、次のようにすると、中括弧の後にfooClassInstanceは使用できなくなりますが、fooInterfaceは使用できなくなります。

public void DoSomething() 
{ 
    IFoo fooInterface; 
    { 
     SomeFoo fooClassInstance = new SomeFoo("test"); 
     fooInterface = (IFoo)fooClassInstance; 
    } 

    // do something with fooInterface, but NOT with fooClassInstance 
} 
+0

私は何かにインターフェイスを渡すので、fooClassInstanceはどうなりますか?さらに、fooClassInstanceが破棄されている間に、渡された場合、インタフェースのBar文字列はどうなりますか? – bleepzter

+1

+1 - ガベージコレクタは参照だけでなくインスタンスを収集することにも注意してください。 *参照を使用して、まだ参照されているインスタンスを見つけます。 – Justin

+2

'fooClassInstance'がスコープから外れると(つまり、中括弧の後ろ)、これは使用できなくなります。しかし、これは変数(ラベル) 'fooClassInstance'だけが' SomeFoo'の実際のインスタンスへの参照として使用できなくなることを意味します。すべての間、インスタンスは(何か 'Bar'文字列がセットされていても)_something_がまだこのインスタンスへの参照を持っているので(この場合は' fooInterface')、メモリ内に残ります。 –

3

使用している点で、いくつかの混乱が(私は他の誰かがその問題に取り組むもらおう)確かにありますが、私はは、私はあなたが言っているかを理解し、あなたが基本的権利だと思い。特に

同僚が、これが起こっていると考えているように、それが聞こえる:

// Now there is this "SomeFoo" object somewhere in memory. 
SomeFoo fooClassInstance = new SomeFoo("test"); 

// Now there is this "IFoo" object somewhere in memory. 
IFoo fooInterface = (IFoo)fooClassInstance; 

// Let's say down the road somewhere, fooClassInstance is set to null or a different 
// object. Your coworker believes that the object it originally pointed to will then 
// have no references to it and will thus be eligible for garbage collection? 

上記は、あなたの同僚はどう思うかの正確な表現であれば、あなたの同僚が間違っている、あなたは正しいです。 fooInterface変数には、fooClassInstanceに参照がある同じオブジェクトへの参照が含まれています。あなたは簡単に、単純に次のようにしてこれを確認することができます

SomeFoo fooClassInstance = new SomeFoo("test"); 
IFoo fooInterface = (IFoo)fooClassInstance; 
bool sameObject = ReferenceEquals(fooClassInstance, fooInterface); 

ReferenceEqualsもし戻っtrue、その後、2つの変数がメモリ内の同じオブジェクトを参照しています。あなたの同僚は、さらに説得力の必要がある場合


は、彼女/彼を示してみてください、このような何か:

List<int> list = new List<int> { 1, 2, 3 }; 

// This cast is actually not needed; I'm just including it so that it mirrors 
// your example code. 
IList<int> ilist = (IList<int>)list; 

// Now we remove an item from the List<int> object referenced by list. 
list.Remove(3); 

// Is it in ilist? No--they are the same List<int> object. 
Console.WriteLine(ilist.Contains(3)); 

// How about we remove an item using ilist, now? 
ilist.Remove(2); 

// Is it in list? Nope--same object. 
Console.WriteLine(list.Contains(2)); 

// And here's one last thing to note: the type of a VARIABLE is not the same 
// as the type of the OBJECT it references. ilist may be typed as IList<int>, 
// but it points to an object that is truly a List<int>. 
Console.WriteLine(ilist.GetType()); 
0

あなたが正しいですが、私たちはの一部が欠けているように私は感じるようです聞こえますオブジェクトを作成(およびキャスト)した後で、オブジェクトを使って何をしているのかわからないため、議論が必要です。あなたの例では

SomeFoo fooClassInstance = new SomeFoo("test"); 

この時点で、あなたはfooClassInstanceによって参照SomeFooオブジェクトへの一つの基準を持っています。この時点で

IFoo fooInterface = (IFoo)fooClassInstance; 

、あなたは(fooClassInstanceとfooInterfaceの両方によって参照)SomeFooオブジェクトへの2つの参照を持っています。

はい、使用方法によっては、fooClassInstanceが範囲外になる可能性があります。しかし、まだそれへの参照(fooInterface)があるので、ガベージコレクションされません。また、fooInterface参照をSomeFooにキャストすることもできます。

関連する問題