Какова основная область применения интерфейса C #? - PullRequest
0 голосов
/ 28 января 2011

У меня возник спор с другим коллегой-программистом по поводу объема интерфейсов.

предположим, что у нас есть следующее:

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.Возможно ли, чтобы fooClassInstance вышел из области видимости, прежде чем что-то еще выпустит экземпляр fooInterface?

Некоторые утверждают, что объект (fooClassInstance) может выйти из области видимости.

Я считаю, чтоэто не могу.Конечно, объекты могут или не могут быть утилизированы GC, когда GC решает, что объект (ы) больше не находится в области видимости.Однако, поскольку интерфейсы являются абстрактным контрактом, члены которого должны быть реализованы объектом, который его использует, интерфейс не может потерять свою реализацию, пока используется интерфейс.Это не совсем другой объект, созданный по типу «интерфейс».Интерфейс является просто указателем на эти абстрактные члены разработчика.

Не могли бы вы, ребята, помочь мне разрешить этот спор?

Спасибо,

<bleepzter />

Ответы [ 4 ]

3 голосов
/ 28 января 2011

Несмотря на определенную путаницу в терминах, которые вы используете (я позволю кому-то еще заняться этим вопросом), я думаю Я понимаю, что вы говорите, и вы в основном правы.

В частности, ваш коллега считает, что это происходит:

// 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());
2 голосов
/ 28 января 2011

Я думаю, что вы путаете грань между экземпляром и ссылкой. 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
}
1 голос
/ 28 января 2011

Э-э, что вы подразумеваете под "потерять свою реализацию"?Это бессмысленно.Тип реализует интерфейс, он не может «реализовывать» интерфейс.

Что касается примера кода, время жизни выделенного объекта заканчивается в тот момент, когда он больше не имеет корней (иначе он более недоступенпо 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 голосов
/ 28 января 2011

Это звучит как будто вы правы, но я чувствую, что мы пропустили часть обсуждения, так как мы не знаем, что вы делаете с объектом после того, как вы его создали (и произвели) .

В вашем примере:

    SomeFoo fooClassInstance = new SomeFoo("test");

На данный момент у вас есть одна ссылка на объект SomeFoo, на который ссылается fooClassInstance.

    IFoo fooInterface = (IFoo)fooClassInstance;

На данный момент у вас есть две ссылки на объект SomeFoo (на которые ссылаются как fooClassInstance, так и fooInterface).

Так что да, в зависимости от того, как вы его используете, fooClassInstance может выйти из области видимости. Но есть ссылка на него (fooInterface), поэтому он не будет собирать мусор. Кроме того, ссылка на fooInterface может быть возвращена к SomeFoo.

...