Kas automatic property on sama mis property?

06.12.2007  |  Gunnar

Kas automatic property on sama, mis property? Jõudsin selle huvipakkuva küsimuseni automaatsete omaduste (automatic property) osas tegelikult tükk aega enne tänast. Nimelt jäin sellele mõtlema ühel TechEd'il toimunud ettekandel, millele eelnenud õhtu osutus oodatust hulka meeleolukamaks. See kanne tutvustab tulemusi, mis ilmnesid automaatsete ja tavaliste omaduste võrdlemisel.

Kontrollimise viime läbi järgmise klassi abil, millele lisame hiljem juurde paar huvipakkuvat lisandit.

public class AutoPropTest
{
    private string name;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }
   
    public string Name2 { get; set; }
}

Kompileerime selle klassi nüüd kokku ja vaatame korra, mis tulemust näeme näiteks Reflector'i abil.

public class AutoPropTest
{
    // Fields
    [CompilerGenerated]
    private string <name2>k__BackingField;
    private string name;

    // Methods
    public AutoPropTest();

    // Properties
    public string Name { get; set; }
    public string Name2 {
        [CompilerGenerated] get;
        [CompilerGenerated] set;
    }
}

Siit on hästi näha see, et automaatne ja tavaline omadus pole sünonüümid. Automaatsele omadusele vastav atribuut on CompilerGeneratedAttribute. Dokumentatsiooni järgi saab selle lisaatribuudi alusel kontrollida, kas tegemist on koodis deklareeritud atribuudiga või siis kompilaatori poolt loodud atribuudiga.

Samuti on atribuuti tutvustavas ülimalt lakoonilises dokumentatsioonis toodud ära see, et seda lisaatribuuti kasutab näiteks SQL Server selleks, et leida kompilaatori poolt genereeritud staatilisi atribuute. See erinevus on nüüd üks asi.

Teine asi on see, et me ei saa tegeleda automaatsele omadusele vastava atribuudiga otse oma koodis. Põhjus lihtne – kompilaator ei lase läbi muutujaid, mille nimi sisaldab nurksulge. Seda, kuidas võiks ja miks ei saa oma koodis automaatsete omaduste käitumist järgi mängida, tutvustab meile Doron Yaacoby oma blogi kandes C# 3.0 New Feature for the Week #1: Automatic Properties.

Kas kompilaatori poolt genereeritud atribuudile saab ligi?

Järgmiseks proovime siis automaatsele omadusele Name2 vastavat atribuuti oma koodis muuta. Otse me sellele viitada ei saa, sest kompileerimise eel, mil me tegeleme lähtekoodi tasandil, seda atribuuti veel olemas ei ole. Küll aga on see atribuut olemas meil peale kompileerimist. Seega tuleb mängu reflection. Kirjutame klassile juurde Name2Direct omaduse. Kood ise on järgmine.

public string Name2Direct
{
    get
    {
        Type t = this.GetType();

        BindingFlags flags = BindingFlags.GetField;
        flags = flags | BindingFlags.Instance;
        flags = flags | BindingFlags.NonPublic;               

        return (string)t.InvokeMember("<name2>k__BackingField", flags, null, this, null);
    }
    set
    {
        Type t = this.GetType();
        BindingFlags flags = BindingFlags.SetField;
        flags = flags | BindingFlags.Instance;
        flags = flags | BindingFlags.NonPublic;
        object[] newValue = new object[] { value };

        t.InvokeMember("<name2>k__BackingField", flags, null, this, newValue);           
    }
}

Järgmiseks proovime, mis juhtub siis, kui püüame väärtustada selle atribuudi otse.

class Program
{
    static void Main(string[] args)
    {
        AutoPropTest autoProp = new AutoPropTest();
        Console.WriteLine("Väärtus praegu: "+autoProp.Name2);
        Console.WriteLine("Omistan JEEE!");
        autoProp.Name2Direct = "JEEE!";
        Console.WriteLine("Uus väärtus: "+autoProp.Name2);

        Console.ReadLine();
    }
}

Nagu testimine näitab, siis saame me vajadusel selle atribuudi kätte reflection'i teel. Kus sellist asja võib vaja minna? Näiteks O/R Mapper'id on üks koht, kus teinekord omistatakse väärtusi otse privaatsetele atribuutidele. Kindlasti annab välja mõelda veel igasugu olukordi, kus äkitselt selline võimalus tore oleks, kuid need vahvad fantaasiad jäägu näiteks selle postituse kommentaarideks.

Kommenteeri

sulge
Saada link e-postiga

© DT 2012 | Creative Commons Attribution-Noncommercial 3.0 License | WordPress