什么是基本C#接口范围?
-
26-10-2019 - |
题
在接口范围内,我正在与另一位程序员提出争议。
假设我们有以下内容:
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。