Мәртебелі өзгерту

Мен .NET әзірлеушімін және OOP туралы өте көп білемін. Алайда жақында мен бір қызықты фактіні байқадым.

System.Data.SqlClient.SqlCommand derives from System.Data.Common.DbCommand. The latter implements System.IDbCommand. System.IDbCommand exposes the property Connection which an instance of IDbConnection. In DbCommand However this property returns DbConnection type. And finally the same property in SqlCommand is of type SqlConnection

Мен бірдей орындауға тырыстым, бірақ ол уақытты қате жіберді. Жоғарыда келтірілген мысалға қалай қол жеткізді және сол үлгіні қалай жасауға болады?

Менің коды (компиляция емес):

public interface IFoo { }
public interface IBar 
{
   IFoo TheFoo();
}

public abstract class AbsFoo : IFoo { }
public abstract class AbsBar : IBar 
{
    public abstract AbsFoo TheFoo();
}

public class ConcreteFoo : AbsFoo { }
public class ConcreteBar : AbsBar { }
1
және Джейсонның екеуін де SqlCommand жасайтын әрекетті орындау үшін Ричардтың жауаптарын пайдалану керек. Екі жауап - тұтастай алғанда екі бөлік.
қосылды автор Enigmativity, көзі

3 жауаптар

Explicit interface implementation is the name of the game here. Try this:

public abstract class AbsBar : IBar {
    IFoo IFoo.TheFoo() { return this.TheFoo(); }
    public abstract AbsFoo TheFoo();
}

4
қосылды
Ойбек: Дұрыс.
қосылды автор jason, көзі
Ол нақты интерфейсті іске асыру салдарынан жасырынып жатыр! (Және компиляция қателігіне өкінемін, уақытты қиып тастаймын, бірақ кешіріңіздер). Құжаттама дұрыс емес.
қосылды автор jason, көзі
@Jason - Сіз тек осы мәселенің жартысына жауап бердіңіз. Ричардтың жауабы екінші жартысы болды. ОС үшін SqlCommand қолданатын адресу үшін және әдісін қолданудың айқын интерфейсін пайдалану қажет.
қосылды автор Enigmativity, көзі
Бұл дұрыс емес және тіпті компиляцияланбайды. Ашық іске асыруға қарсы тұру проблеманы шешпейді.
қосылды автор Richard Hein, көзі
@Jason Директиваларды пайдалану Сіздің кодыңыз құрастырылмайды. Және SqlCommand байланысының басқа түрін қайтаруының себебі DbCommand қарағанда, себебі Connection - жай ғана жалпы сипат. Сіз компиляция қателесеңіз: «Редакциялаушы» бұл элемент үшін жарамсыз «. Құжаттама дұрыс емес, Нысан шолушысын қарап, DbCommand.Connection үшін қолтаңбаны көресіз. Public DbConnection Connection {get; жиынтығы; } және SqlCommand.Connection үшін қолтаңба SqlConnection қосылымы {get; жиынтығы; }. Мен оған дұрыс қараймын.
қосылды автор Richard Hein, көзі
Сонымен қатар, егер сіз SqlCommand-ге Нысан шолушысында қарасаңыз және Show Inherited Members-да қосылсаңыз, DbConnection және басқа SqlConnection-ді қайтаратын екі қосылым сипатын көресіз, бірақ DbConnection қайтаратын кәдімгі қатынастан жасырылады.
қосылды автор Richard Hein, көзі
Мен IBar.TheFoo() деп аннотация ретінде және екінші әдіс жария дерексіз ретінде белгілеймін, бірақ ол маған әлі де компилятор қатесін береді
қосылды автор Oybek, көзі
Өкінішке орай, нақты мәлімделген әдісті енгізу қажет. Мен мұны дерексіз деп айта алмаймын.
қосылды автор Oybek, көзі

I have to say that I think Richard was a little hard done by - his answer is just as good as Jason's in that they both only answered half of the question. Put them both together and you have the full answer.

To make this work with IDbCommand, DbCommand & SqlCommand there has to be an explicit implementation of IDbCommand in DbCommand (Jason's answer) and public method shadowing in SqlCommand (Richard's answer).

Мен толық «Foo/Bar» мысалын беремін.

Мына интерфейстерден бастаңыз:

public interface IFoo
{
    IBar GetBar();
}

public interface IBar { }

Келесі Foo өзінің IBar емес, кодын қайтару үшін IFoo код> GetBar әдісі:

public abstract class Foo : IFoo
{
    IBar IFoo.GetBar()
    {
        return this.GetBar();
    }

    public Bar GetBar()
    {
        return this.GetBarInner();
    }

    protected abstract Bar GetBarInner();
}

public abstract class Bar : IBar { }

Сонымен, SomeFoo данасын SomeFoo данасын қайтару үшін GetBar көлеңкесінде SomeFoo

public class SomeFoo : Foo
{
    public new SomeBar GetBar()
    {
        return new SomeBar();
    }

    protected override Bar GetBarInner()
    {
        return this.GetBar();
    }
}

public class SomeBar : Bar { }

Менің ойымша, Ричардтың тек new кілт сөзін қосудың көлеңкеленген әдіске қосылатын жалғыз ақпарат деп ойлаймын, сіз компилятордың қателігінен құтыласыз.

2
қосылды
Хорор 3-ші партиялық байқау үшін. :)
қосылды автор Richard Hein, көзі

DbCommand және SqlCommand-те қосылу тек жай ғана қоғамдық әдістер болып табылады. Компилятор ескертуі болады, бірақ оған рұқсат етіледі. Сіздің кодыңыз бұған SqlCommand/DbCommand сияқты жұмыс істеуі керек:

    public interface IFoo { }
public abstract class AbsBaseBar
{
    public IFoo TheFoo() { throw new NotImplementedException(); }
}
public class AbsFoo : IFoo { }
public class AbsBar : AbsBaseBar
{
    public AbsFoo TheFoo() { throw new NotImplementedException(); }
}

public class ConcreteFoo : AbsFoo { }
public class ConcreteBar : AbsBar { } 
1
қосылды
Менің ойымша, сіз мұнда Ричардтың біраз қиын әрекетін жасадық - сіз дұрыс жауаптың жартысын деп жауап бердіңіз. Джейсон сіздің жартысын толық өткізбеді. Мен сізді терісінен құтқару үшін көтерілім бердім.
қосылды автор Enigmativity, көзі