在接口范围内,我正在与另一位程序员提出争议。

假设我们有以下内容:

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实例之前脱离范围?

有人认为该对象(fuoclassinstance)可以脱离范围。

我相信它不能。当然,当GC决定对象不再存在范围时,对象可能会或可能不会被GC处置。但是,由于接口是通过设计的抽象合同,其成员必须由使用它的对象实现,因此,只要使用接口,就不能丢失其实现。这不是一个整体的另一个对象是“接口”类型。该界面只是指向实施者的那些抽象成员的指针。

你们能帮我解决这一争端吗?

谢谢,

<bleepzter />
有帮助吗?

解决方案

嗯,您是什么意思是“失去其实施”?这是没有意义的。一种类型实现接口,它不能“删除”接口。

就您的代码示例而言,分配的对象末端的寿命不再具有任何根源(AKA,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;
}

其他提示

虽然您使用的术语肯定有一些混乱(我会让别人解决这个问题),但我 思考 我了解您在说什么,您基本上是对的。

特别是,听起来您的同事认为这正在发生:

// 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, ,然后两个变量在内存中引用相同的对象。


如果您的同事需要进一步说服力,请尝试向他/她展示类似的东西:

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());

我认为您在实例引用之间混淆了界限。 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
}

听起来 就像您是正确的一样,但是我觉得我们缺少讨论的一部分,因为我们不知道您在创建(和铸造)之后您在做什么。

在您的示例中:

    SomeFoo fooClassInstance = new SomeFoo("test");

在这一点上,您有一个引用FuoClassInstance引用的somefoo对象。

    IFoo fooInterface = (IFoo)fooClassInstance;

在这一点上,您有两个引用对Somefoo对象(由FooclassInstance和FooInterface引用)。

因此,是的,根据您的使用方式,FooclassInstance可能会出现范围。但是仍然有一个引用(foointerface),因此不会收集垃圾。另外,可以将foointerface引用归还给Somefoo。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top