Galin Iliev

Software Architecture & Development

Ïîäðàçáèðàíå íà òèïà íà ïðîìåíëèâèòå

Ïðåäïîëàãàì, ÷å çàáåëÿçàõòå â ÷àñòòà Ôèëòðèðàíå ñ LINQ è C# 3.0, ÷å èçïîëçâàõìå êëþ÷îâàòà äóìà var âìåñòî ïîçíàòèòå íè òèïîâå.  òàçè è ïîñëåäâàùàòà ÷àñò, ÷å îáÿñíèì ïîäðîáíî çàùî.

Êàòî ðàçðàáîò÷èöè íà C# çíàåì, ÷å ïðîìåíëèâè ñå äåêëàðèðàò ïî òîçè íà÷èí

<èìå íà òèïà> <èìå íà ïðîìåíëèâà> [ = èíèöèàëèçàöèÿ];

Êúäåòî:

·         <èìå íà òèïà> - òèï íà ïðîìåíëèâàòà (string, int, SqlCommand èëè äðóãî èìå íà êëàñ), êîéòî ïîêàçâà êàêâè äàííè ùå ñå ñúäúðæàò â äåêëàðèðàíàòà ïðîìåíëèâà

·         <èìå íà ïðîìåíëèâà> - íàèìåíîâàíèå íà ïðîìåíëèâàòà, êîåòî ùå èçïîëçâàìå ïî-êúñíî â êîäà. Èìà ìíîãî ëèòåðàòóðà, êîèòî îïèñâàò êàê òðÿáâà äà ñå êðúùàâàò ïðîìåíëèâèòå è âñè÷êè ñå ñúãëàñÿâàò, ÷å èìåòî òðÿáâà äà å ïîêàçâà çíà÷åíèåòî íà äàííèòå, êîèòî ñå ñúõðàíÿâàò â ïðîìåíëèâàòà. (Ïðèìåð çà äîáðè èìåíà – customerDiscount, databaseConnection. Ëîøè èìåíà – alabala, rf0j;)

·         [ = èíèöèàëèçàöèÿ]òîâà å ÷àñòòà, êúäåòî ñå èçâèêâàò êîíñòðóêòîðèòå íà êëàñîâåòå èëè äàííèòå íà ïðîìåíëèâèòå.

Êàêòî, ñèãóðíî, ñå äîñåùàòå êëþ÷îâàòà äóìà var çàìåñòâà èìåòî íà òèïà. Òîâà îçíà÷àâà, ÷å ïðîìåíëèâèòå äåêëàðèðàíè ïî òîçè íà÷èí:

var text1 = "This is text. ";
var num = 12;

ñà èäåíòè÷íè íà ïðîìåíëèâèòå äåêëàðèðàíè ïî ïîçíàòèÿò íè íà÷èí:

string text1 = "This is text. ";
int num = 12;

Òóê ïî-íàïðåäíàëèòå ÷èòàòåëè ìîæå áè ñè çàäàâàò âúëíà îò âúïðîñè: Íå å ëè ñúùîòî àêî âìåñòî var èçïîëçâàìå object? Èëè Variant çà äíèòå íà VB6 è COM? À êàêâî ñòàíà ñ èäåÿòà çà ñèëíî òèïèçèðàíèòå ïðîìåíëèâè?

Îòãîâîðèòå íà òåçè âúïðîñè ùå ïîòúðñèì ñ âå÷å ïîçíàòèÿò íè èíñòðóìåíò Reflector. Íåêà äà äåêîìïèëèðàìå àñåìáëè, â êîåòî ñìå äåêëàðèðàëè ïðîìåíëèâè ñ var. Çà äà íàïðàâèì íåùàòà ïî-èíòåðåñíè ùå äîáàâèì äåêëàðàöèÿ íà êëàñ:

var text1 = "This is text. ";
var num = 12;
var connection = new SqlConnection("connection string here");

Ñëåä êîìïèëàöèÿòà (ñ êîìïèëàòîðà îò LINQ Preview (May 2006)) è ðàçãëåæäàíå íà àñåìáëèòî ñ Reflector, âèæäàìå ñëåäíîòî:

string text1 = "This is text. ";
int num = 12;
SqlConnection connection = new SqlConnection("connection string here");

Èíòåðåñíî... Êàêòî áèõìå ãî íàïèñàëè è â C#2.0. Òîâà îçíà÷àâà, ÷å êîìïèëàòîðà ðàçïîçíàâà äàííèòå è ïîñòàâÿ ïðàâèëíèÿò òèï. Òîâà äåéñòâèÿ íå å ïî âðåìå íà èçïúëíåíèå (çà ðàçëèêà îò Variant) èëè ïî âðåìå íà ñúçäàâàíå íà ïðèëîæåíèåòî (design time), à ïî âðåìå íà êîìïèëàöèÿ.

Ïî òàçè ïðè÷èíà, êîãàòî ñå èçïîëçâà var ïðîìåíëèâèòå òðÿáâà äà ñå èíèöèàëèçèðàò íà ñúùèÿò ðåä.  ïðîòèâåí ñëó÷àé êîìïèëàòîðúò íÿìà äà èìà ïðåäñòàâà çà äàííèòå, êîèòî ùå ñå ñúõðàíÿâàò. Òàçè ìàëêà õèòðèíà ñàìî ïðèâèäíî ðàçìèâà èäåÿòà çà ñèëíî òèïèçèðàíè ïðîìåíëèâè.

Êàêòî èçãëåæäà òàçè íîâà åçèêîâà êîíñòðóêöèÿ âúâåæäà ãîëÿìî óëåñíåíèå çà ðàçðàáîò÷èöèòå. Àêî ñè ïðåäñòàâèì ìåòîä ñ äâàäåñåòèíà ïðîìåíëèâè, äåêëàðèðàíè ñ var, ùå å òðóäíî äà çàïîìíèì òèïà íà âñÿêà åäíà îò òÿõ, à è íÿìà äà ìîæå äà ãî ïðî÷åòåì âåäíàòà, à òðÿáâà äà ïîãëåäíåì è èíèöèàëèçèðàùàòà ñåêöèÿ. Òîâà áè íàïðàâèëî êîäà íå÷åòèì.

Äåêëàðèðàíåòî íà ïðîìåíëèâè ñ êëþ÷îâàòà äóìà var òðÿáâà äà ñòàâà ñàìî çà Àíîíèìíè òèïîâå è êîëåêöèè âðúùàíè îò ìåòîäèòå íà LINQ. Íåíóæíîòî èçïîëçâàíå ìîæå äà äîâåòå äî íàìàëÿâàíå êà÷åñòâîòî íà ïðîãðàìíèÿò êîä è ïîñëåäâàùà ïðîìÿíà (maintenance).

Íà ïðúâ ïîãëåä òàçè ìàëêà êëþ÷îâà äóìè÷êà èìà ìíîãî ìàëúê ïðèíîñ. Íî òîâà å ñàìî íà ïðúâ ïîãëåä, êàêòî ùå âèäèì â ñëåäâàùàòà ÷àñò – Àíîíèìíè òèïîâå.

Àíîíèìíè òèïîâå

Õàðàêòåðíî çà ïðîãðàìíèòå åçèöè äî ìîìåíòà å ñëåäíèÿò íà÷èí çà ðàáîòà ñ äàííè:

·         Äåôèíèðàíå íà òèïîâåòå äàííè – äåêëàðèðàíå íà êëàñîâå, ñòðóêòóðè

·         Èíèöèàëèçèðàíå íà ïðîìåíëèâà îò òèï äåôèíèðàí â ïðåäõîäíàòà òî÷êà

·         Èçïîëçâàíå íà äàííèòå – ïîïúëâàíå, ÷åòåíå, ïðîìÿíà íà ñâîéñòâàòà íà îáåêòèòå.

Ïî òîçè íà÷èí ñå ñúçäàâàò îáåêòèòå â ò.íàð áèçíåñ ñëîé (business layer). Êàêòî âèíàãè, îáà÷å, íåùàòà íå ñïèðàò äî òóê è ñëåäâà íå ìàëêî óñëîæíåíèå – äàííèòå ñå ñúõðàíÿâàò â îòäåëåí ñëîé (SQL Server), êîéòî èçïîëçâà ðàçëè÷íè íà÷èíè çà ñúõðàíåíèå íà äàííèòå. Òîâà íàëàãà ñâúðçâàíå ìåæäó äàííèòå â ñëîÿ çà ñúõðàíåíèå (data tier) ñ áèçíåñ ñëîÿ. (Ïî-êúñíî ùå ðàçãëåäàìå ïîäðîáíî êàê ñå îñúùåñòâÿâà òîâà ñâúðçâàíå ñ ïîìîùòà íà C# 3.0 è Visual Studio Codename “Orcas”).

Íå áèâà äà ñå ïðåíåãðåãâà ìîìåíòà, â êîéòî ñå íàëàãà äà ñå ïðîìåíÿò èçïîëçâàíèòå äàííè. Òîãàâà ñå íàëàãà ïðîìÿíà íà äåôèíèðàíèòå êëàñîâå è êîäà, êúäåòî ñå èçïîëçâàò òå. À àêî ñà ñâúðçàíè ñúñ ñëîé çà ñúõðàíåíèå, òî òîãàâà ñå íàëàãàò ïðîìåíè è â íåãî.

Çàáåëåæêà: Ïî-÷åñòî â ïðàêòèêàòà ïðîìåíèòå â áèçíåñ ñëîÿ ñå íàëàãàò çàðàäè ïðîìåíè ñëîÿ ñ äàííè, íî çà öåëòà íà àáñòðàêöèÿòà ðàçãëåæäàìå äâàòà âàðèàíòà – ñ è áåç ñëîé çà ñúõðàíåíèå.

Êàêòî ìîæå äà ñå ïðåäïîëîæè, èçèñêâàíåòî çà íÿêàêâà ïðîìÿíà â äàííèòå íà ïðèëîæåíèåòî èçèñêâà ìíîæåñòâî ïðîìåíè â êîäà. Äîêàòî íå ìîæå äà ñå èçáÿãà (âñå îùå) îò ïðîìÿíàòà íà ïîòðåáèòåëñêèÿ èíòåðôåéñ, â çàâèñèìîñò îò äàííèòå, òî àíîíèìíèòå òèïîâå ïðåäîñòàâÿò óäîáåí è ëåñåí íà÷èí çà ðàáîòà ñ äàííè, êîèòî ÷åñòî ñå ïðîìåíÿò.

Çà ìîìåíòà ùå ïðåäñòàâèì êàê ñå ïîñòèãà òîâà, à ïðàêòè÷åñêàòà ïîëçà ùå èçëåçå íàÿâå, êîãàòî ðàçãëåæäàìå LINQ â äåòàéëè.

Íåêà ñå âúðíåì íà ïðåäèøíèÿò ïðèìåð ñ êëàñà Customer. Ñ ïîìîùòà íà íîâèòå åçèêîâè êîíñòðóêöèè ìîæå äà ñå èíèöèàëèçèðà ïî òîçè íà÷èí:

Customer cust = new Customer { Id=1, Name="John Atanasov" };

Òîâà óëåñíÿâà ìíîãî èíèöèàëèçàöèÿòà íà îáåêòà, íî âñå îùå èçèñêâà äåêëàðàöèÿ íà êëàñà Customer. Àêî èñêàìå äà èçïîëçâàìå äàííè çà ñëóæèòåë áåç äà äåôèíèðàìå êëàñ çà íåãî òîâà ìîæå äà ñòàíå òàêà:

var employee = new {Id=15, Name="Galin", Experience = 8, ManagerId=2};

è ìîæå äà èçïîëçâàìå òàêà ñúçäàäåíàòà è èíèöèàëèçèðàíà ïðîìåíëèâà â ñúùèÿò ìåòîä:

Console.WriteLine(employee.Name);

èëè ïî íà÷èí, êîéòî íàìåðèì çà äîáðå. Òîâà å èçêëþ÷èòåëíî óäîáíî â LINQ çàÿâêè, êîèòî ñîðòèðàò, ãðóïèðàò è âðúùàò íîâè ñòðóêòóðè îò äàííè. Àêî òðÿáâà äà ñå äåôèíèðàò ïðåäâàðèòåëíî âñè÷êè êëàñîâå, òîâà áè îòíåëî ìíîãî âðåìå. (âèæ ïðèìåðà îò Ãðóïèðàíå ñ LINQ è C# 3.0)

Íåêà äà íàâëåçåì â äúëáèíèòå íà òàçè ôóíêöèîíàëíîñò è äà âèäèì êàê òîâà ñòàâà âúçìîæíî. Îòíîâî èçïîëçâàìå Reflector è ïðè ðàçãëåæäàíå íà êîìïèëèðàíîòî àñåìáëè îòêðèâàìå ñëåäíèÿò êëàñ:

[CompilerGenerated]

public sealed class <Projection>f__0

{

      // Methods

      public <Projection>f__0();

      public override bool Equals(object);

      public override int GetHashCode();

      public override string ToString();

  

      // Properties

      public int Experience { get; set; }

      public int Id { get; set; }

      public int ManagerId { get; set; }

      public string Name { get; set; }

  

      // Fields

      private int _Experience;

      private int _Id;

      private int _ManagerId;

      private string _Name;

}

Âå÷å ñòàâà ïî-ÿñíî, íàëè? Êàêòî èçãëåæäà îòíîâî êîìïèëàòîðà âúðøè íåïðèÿòíàòà ÷àñò îò ðàáîòàòà, êàòî ãåíåðèðà êëàñ, â çàâèñèìîñò îò äàííèòå/ñâîéñòâàòà îò êîèòî èìàìå íóæäà. Ïî òîçè íà÷èí, êîãàòî ñå íàëîæè äà ïðîìåíÿìå êëàñà, ïðîñòî òðÿáâà äà ïðîìåíèì èíèöèàëèçàöèÿòà (è èçïîëçâàíåòî ) íà êëàñà, íî íå òðÿáâà äà ñå ãðèæèì äà ïðîìÿíà íà äåôèíèöèÿòà.

Êîìïèëàòîðà èìà è ìåõàíèçúì çà îïòèìèçàöèÿ, êîéòî èçïîëçâà âå÷å ãåíåðèðàíèÿò êëàñ àêî èçïîëçâàìå äâå ïðîìåíëèâè ñ åäíàêâè ñâîéñòâà. Àêî ïðîìåíèì ñâîéñòâàòà, îáà÷å, íîâ àíîíèìåí êëàñ ñå ãåíåðèðà.

 

Ñëåäâàùà ÷àñò: Àâòîìàòè÷íî èçãðàæäàíå íà ñâîéñòâà

Content