0

インターフェイスの範囲について、他のプログラマーと争っています。

次のものがあるとします。

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によって破棄される場合とされない場合があります。ただし、インターフェイスは設計上、それを使用するオブジェクトによってメンバーを実装する必要がある抽象コントラクトであるため、インターフェイスが使用されている限り、インターフェイスはその実装を失うことはありません。「interface」タイプの別のオブジェクトが作成されるわけではありません。インターフェイスは、実装者の抽象メンバーへのポインタにすぎません。

この論争を解決するのを手伝ってくれませんか。

ありがとう、

<bleepzter />
4

4 に答える 4

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());
于 2011-01-27T21:23:02.433 に答える
2

インスタンス間の境界線を参照していると思います。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
}
于 2011-01-27T21:16:38.557 に答える
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;
}
于 2011-01-27T21:18:38.600 に答える
0

あなたは正しいように聞こえますが、オブジェクトを作成(およびキャスト)した後、オブジェクトで何をしているのかわからないため、ディスカッションの一部が欠落しているように感じます。

あなたの例では:

    SomeFoo fooClassInstance = new SomeFoo("test");

この時点で、fooClassInstanceによって参照されるSomeFooオブジェクトへの参照が1つあります。

    IFoo fooInterface = (IFoo)fooClassInstance;

この時点で、SomeFooオブジェクトへの2つの参照があります(fooClassInstanceとfooInterfaceの両方によって参照されます)。

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

于 2011-01-27T21:23:11.330 に答える