Модераторы: Partizan, gambit
  

Поиск:

Закрытая темаСоздание новой темы Создание опроса
> Не компилируется... Почему? 
V
    Опции темы
Vit
Дата 4.5.2007, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: 1
Всего: 207



Создал я 3 класса и работать это не хочет... Вопервых непонятно почему, во вторых - а как быть?
Код


public abstract class Param // абстрактный класс предок, определены общие методы, 
// остальные members задекларированы как абстрактные
{
... чего-то там
}

public class StrParam : Param // реальный, рабочий класс, работает со строками, 
//все members такие же как в Param, но абстрактные методы класса-предка перекрыты 
{
... чего-то там
}

public class IntParam : Param  // реальный, рабочий класс, работает со целыми числами, 
//все members такие же как в Param, но абстрактные методы класса-предка перекрыты 
{
... чего-то там
  }

public class MyClass // мой рабочий класс, где мне надо оперировать с обозначенным выше
{

 public List<Param> ParamList =new List<Param>(); //лист который может хранить любые параметры
 public IntParam Category = new IntParam(чего-то там);
 public StrParam Location=new StrParam( чего-то там);

 protected string ReadParam(StrParam Param)
 {//overloaded метод для работы с переменной класса  StrParam 
... чего-то там
 }

 protected int ReadParam(IntParam Param)
 {//overloaded метод для работы с переменной класса  IntParam 
... чего-то там
 }

 public string Builder()
 {
// наполняю лист разного типа параметрами
  ParamList.Add(Category);
  ParamList.Add(Location);
... чего-то там

  foreach (Param p in ParamList)
  {
   чего-то там = ReadParam(p); // Вот тут то компиллятор и показывает мне дулю на резине!
  }

... чего-то там





Ошибка: cannot convert from 'Param' to 'StrParam'   smile  smile  Дык это ж общий предок!!! А на фига тогда вообще ООП нужно, если класс потомка нельзя передавать как класс предка???

Это сообщение отредактировал(а) Vit - 4.5.2007, 00:42


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
stab
Дата 4.5.2007, 01:58 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



до настолько динамической перегрузки языки ещё не дошли. ты пытаешся сделать, чтобы во время выполнения исходя из типа параметра вызывался соответсвующий перегруженный метод. не бывает так.

как вариант: можно определить ReadParam виртуальным в классе Param, и во всех потомках дать ему свой функционал (перекрыть). тогда цикл чтения будет выглядеть примерно так:

Код

foreach (Param p in ParamList)
{
    p.ReadParam(some place to read from.. stream?);
}


полиморфизм короче. при таком варианте считанные данные лучше всего хранить в самом экземпляре потомка Param.

.. или ещё как-то передизайнить код  smile 


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
Hurricane
Дата 4.5.2007, 07:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 10.4.2007

Репутация: 3
Всего: 9



Цитата(cully)
...исходя из типа параметра вызывался соответсвующий перегруженный метод...

Точнее даже не из типа параметра, а из типа возвращаемого значения.

Vit, в принципе, можно извернуться и сделать, как ты хочешь, но это сводит на нет всю идею объектно-ориентированного программирования:
Код

foreach( Param param in ParamList )
{
    IntParam    iParam = param as IntParam;
    StringParam sParam = param as StringParam;

    if ( iParam != null )
    {
        int myInt = iParam.ReadParam();
    }
    else if ( sParam != null )
    {
        string myString = sParam.ReadParam();
    }
}

т.е. ты сам выясняешь, какого типа на самом деле текущий элемент списка, и вызываешь соответствующий метод.
Лучше, наверно, что-то типа вот так:
Код

    abstract class BaseParam
    {
        abstract public void ReadParam();
    }

    class IntParam : BaseParam
    {
        public override void ReadParam()
        {
            // делает что-то с типом int
        }
        private int _param;
    }

    class StringParam : BaseParam
    {
        public override void ReadParam()
        {
            // делает что-то с типом string
        }
        private string _param;
    }

    // где-то в программе
    foreach ( BaseParam param in ParamList )
    {
        param.ReadParam();
    }


Но лучше всего сделать, как написал cully, только придется передизайнить. Проблема будет в том, что ты хочешь получать возвращаемые значения из метода ReadParam(), но они, по идее, разные (int и String). Можно возвращать object, но это проблемы не решает - под ним может скрываться int или string. А надо ли их различать? Допустим, нам надо вывести это значение в поток. Вот и передадим ему поток, пусть он сам себя и выводит:
Код

    abstract class BaseParam
    {
        abstract public void ReadParam(StreamWriter);
    }

    class IntParam : BaseParam
    {
        public override void ReadParam(StreamWriter sw)
        {
            sw.WriteLine("This is int, value = {0}", _param);
        }
        private int _param;
    }

    class StringParam : BaseParam
    {
        public override void ReadParam(StreamWriter sw)
        {
            sw.WriteLine("This is string, value={0}", _param);
        }
        private string _param;
    }

    // где-то в программе
    StreamWriter sw = new StreamWriter(...);
    foreach ( BaseParam param in ParamList )
    {
        param.ReadParam(sw);
    }





Это сообщение отредактировал(а) Hurricane - 4.5.2007, 07:13
PM MAIL   Вверх
adLucem
Дата 4.5.2007, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 17.4.2007
Где: Украина, Донецк

Репутация: 4
Всего: 5



Цитата(Vit @  3.5.2007,  22:33 Найти цитируемый пост)
Ошибка: cannot convert from 'Param' to 'StrParam'   smile  smile  Дык это ж общий предок!!! А на фига тогда вообще ООП нужно, если класс потомка нельзя передавать как класс предка???

Полиморфизм обеспечивает приведение от потомка к предку, но не от предка к потомку (потому что, в общем случае, неизвестно к какому потомку приводить).

Теория
Допустим имеем следующую иерархию:
Код

class A {
}
class B : A {
}
class C : B {
}

class D {
    void processing ( B value ) {
    }
    void processing ( C value ) {
    }
    void processingFoo ( ) {
        A value = new C ( );
        processing ( value ); 
        // Вот в этом месте возникает вопрос - к чему приводить value
        // 1. Приводить к В и использовать processing ( B value )
        // 2. Приводить к С и использовать processing ( C value )
        // Такая ситуация не может быть разрешена компилятором.
    }
}


В вашем случае иерархия более проста, но компилятор также не будет пытаться разрешить тип потомка относительно предка. Любое приведение от типа предка к типу потомка считается неоднозначным в статических языках.

Практика
Анализ ошибки
Код

protected string ReadParam(StrParam Param) {
}

protected int ReadParam(IntParam Param) {
}

public string Builder() {
// наполняю лист разного типа параметрами
    ParamList.Add(Category);
    ParamList.Add(Location);

    //Из списка получен объект базового класса
    foreach (Param p in ParamList){
    // ReadParam перегружен, так как перегруженного метода, который бы принимал Param нет, то анализируются имеющиеся методы на наличие наиболее подходящей сигнатуры
    // Если компилятор попытался использовать StrParam, то скорее всего "[I]чего-то[/I]" там у вас имеет тип string
    // Так неявного (implicit) приведения Param к StrParam или IntParam не предусмотрено компилятор выдает ошибку
    чего-то там = ReadParam(p); // Вот тут то компиллятор и показывает мне дулю на резине!
    }


Исправленный код (внесены некоторые изменения в код Hurricane)
Сохранение результатов динамического приведения во временной переменной - рекомендация Microsoft (см. FxCop 1.35).
Код

foreach (Param p in ParamList){
    IntParam intP = p as IntParam;
    if ( !ReferenceEquals ( intP, null ) ) {
        чего-то там = ReadParam ( intP ); //вызов ReadParam(IntParam Param)
        return;
    }
    StrParam strP = p as StrParam ;
    if ( !ReferenceEquals ( strP , null ) ) {
        чего-то там = ReadParam ( strP ); //вызов ReadParam(StrParam Param)
        return;
    }
}


Исправленный код (вариант 2)
Более красивый вариант с точки зрения кода (имхо), но с дополнительными затратами на повторяющееся динамическое приведение типов.
Код

foreach ( Param p in ParamList ) {
    if ( p is IntParam ) {
        чего-то там = ReadParam ( p as IntParam ); //вызов ReadParam(IntParam Param)
    } else if ( p is StrParam ) {
        чего-то там = ReadParam ( p as StrParam ); //вызов ReadParam(StrParam Param)
    }
}



Возможно вынесение полиморфного поведения в наследники (см. пост Hurricane), но это не всегда допустимо. Если программа требует динамического определения типа то возможно нужно провести рефакторинг и перенести полиморфное поведение в классы наследники (см. предыдущие посты).

Это сообщение отредактировал(а) adLucem - 4.5.2007, 10:34
PM MAIL ICQ   Вверх
tol05
Дата 4.5.2007, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Извините что вмешался, но почитав пост adLucem 

Цитата(adLucem @  4.5.2007,  09:11 Найти цитируемый пост)
Полиморфизм обеспечивает приведение от потомка к предку, но не от предка к потомку (потому что, в общем случае, неизвестно к какому потомку приводить)


вынужден сказать, что я понимаю полиморфизм по-другому smile. Только теория, код, я думаю каждый из нас свой напишет (и неплохой).

Класс потомка всегда нужно передавать в качестве класса предка. И вызывать нужно всегда методы предка. Только они, конечно должны быть переопределены overrided в потомках. 
НИКОГДА НЕ НУЖНО ПРОВЕРЯТЬ ТИП - ЭТО ЗАБИВАНИЕ ГВОЗДЕЙ МИКРОСКОПОМ. Еще Reflection для анализа типов использовать можно!
Нафиг тогда полиморфизм? Виртуальные функции? Перекрой методы в потомке и именно они для каждого потомка и будут вызываться. В таблице методов потомка будут прописаны ИХ адреса. 
Отличие виртуальных методов от невиртуальных в том, что адреса виртуальных методов в таблице методов предка переписываются на адреса потомков. Обращение к методу класса для невиртаульных функций - на адрес в таблице класса, под которым объявлена ссылка, для виртуальных - на адрес в таблице класса, под которым создан объект!

Когда ссылка класса предка ссылается на объект класса потомка и происходит вызов функции, то идет обращение к указателю на таблицу методов объекта (он реально - потомок). При создании потомка он получил (когда класс загружался в память) таблицу методов предка и переписал в ней адреса виртуальных ф-ций на адреса своих , ну и еще свои, новые написал. 
Компилятор только проверяет, чтобы обращения к методам были в объеме родительской таблицы (объеме класса ссылки, которая СЕЙЧАС на этот объект в куче ссылается) и все. А в run-time объект, под какой бы он ссылкой ни находился, хоть под object, сам хранит в себе истинную таблицу (ее доступность только усекается время от времени или восстанавливается).

Одним словом сделай в базовом классе 
Код

protected virtual string ReadParam(Param param)


в потомках
Код

protected override string ReadParam(Param param)


и везде вызывай одинаково
Код

Param p = new Param();
Param strP = new strParam();
Param intP = new intParam();
Param temp = p;

temp.ReadParam(strP);
temp.ReadParam(intP);

Param temp = strP;

temp.ReadParam(p);
temp.ReadParam(intP);

Param temp = intP;

temp.ReadParam(p);
temp.ReadParam(strP);



Да, кстати, когда в методе анализируется тип переданного параметра, то тоже происходит проверка допустимости его использования в качестве типа, указанного при объявлении метода. И приведение будет неявным.

Извините за многословность и не академическое изложение.

Это сообщение отредактировал(а) tol05 - 4.5.2007, 10:11


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
adLucem
Дата 4.5.2007, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 17.4.2007
Где: Украина, Донецк

Репутация: 4
Всего: 5



 smile 
 smile tol05 - измените свой тон пожалуйста и не заявляйте излишних претензий:

Цитата(tol05 @  4.5.2007,  08:03 Найти цитируемый пост)
НИКОГДА НЕ НУЖНО ПРОВЕРЯТЬ ТИП - ЭТО ЗАБИВАНИЕ ГВОЗДЕЙ МИКРОСКОПОМ

С теоретической точки зрения это конечно же звучит прекрасно, но с практической динамическое приведение типов - это полноценный ООП инструмент, который используется также как и другие инструменты и для применения которого есть достаточно серьезные основания.

Кроме того не следует дублировать решения (имхо), которые уже освещены (см. пост Hurricane).

Цитата(tol05 @  4.5.2007,  08:03 Найти цитируемый пост)
Только теория, код, я думаю каждый из нас свой напишет (и неплохой).
 
Если вы решили теоретизировать - то ссылайтесь на источники. И если уж пишите теорию (которую кстати написали до вас и весьма неплохо), то зачем вы все таки приводите код?


Извиняюсь за  smile .
PM MAIL ICQ   Вверх
tol05
Дата 4.5.2007, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



За тон извиняюсь.
По поводу

Цитата(adLucem @  4.5.2007,  10:25 Найти цитируемый пост)
полноценный ООП инструмент, который используется также как и другие инструменты и для применения которого есть достаточно серьезные основания

оснований не вижу. Методов, добавленных в потомки и требующие вызовов через ссылку базового класса не вижу, а ВЫ?

З.Ы. Право ссылаться на источники я с удовольствием предоставляю Вам. smile


Это сообщение отредактировал(а) tol05 - 4.5.2007, 10:36


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
adLucem
Дата 4.5.2007, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 17.4.2007
Где: Украина, Донецк

Репутация: 4
Всего: 5



Цитата(tol05 @  4.5.2007,  08:33 Найти цитируемый пост)
Методы, добавленные в потомки и требующие вызовов через ссылку базового класса не вижу


Наследование применяется с двумя целями расширение и специализация [Мейер Б. "Конструирование объектно-ориентированных систем"].

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

В случае расширения классы наследники могут предоставлять дополнительные сервисы, которых нет у базового класса. В таком случае клиентский код, для вызова дополнительных сервисов, должен осуществлять динамическое приведение типов.

Специализация и расширение часто комбинируются, что зачастую связано с тем, что разработчики расширений не имеют доступ к исходному коду базовых библиотек (в которых описаны расширяемые классы). Это усложняет логику клиента, требуя ввода дополнительных конструкций ветвления и в последующем может устраняться с применением рефакторинга (если дополнительные сервисы можно перенести в базовый класс и имеется доступ к базовому классу, в частности [Кериевски "Рефакторинг с применением шаблонов"]).

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

Пример (кстати пример не такой уж надуманный и если вы все еще не согласны, то могу дать описание реальной архитектуры, где несмотря на использование ссылки на базовый класс необходимо применение динамического приведения типа).
Код

public class BaseFoo {
    public abstract BaseService ( );
}

public class SpecialFoo : BaseFoo {
    public override BaseService ( );
    public abstract SpecialService ( );
}

public class VerySpecialFoo :  {
    public override BaseService ( );
    public override SpecialService ( );
}

public class ClientFoo {
    public void processing ( BaseFoo foo ) {
        foo.BaseService ( );
        if ( foo is SpecialFoo ) {
            ( foo as SpecialFoo ).SpecialService ( );
        }
    }
}


Это сообщение отредактировал(а) adLucem - 4.5.2007, 10:51
PM MAIL ICQ   Вверх
adLucem
Дата 4.5.2007, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 17.4.2007
Где: Украина, Донецк

Репутация: 4
Всего: 5



Пример архитектуры с применением динамического приведения типов.

В данной архитектуре (основана на модели доменной области) классам SqlReceiver требуется специализированный объект сессии SqlSession, но он должен принимать указатель на более общий класс (в данном случае интерфейс), потому что все получатели создается универсальной динамической фабрикой, которая создает получатели для разных видов сессий, которые определяются после запуска приложения. То есть сам по себе получатель использует только специализацию, но требует расширения от сессии.
Код

// Базовый класс
public class Receiver {
    public Receiver ( ISession session ) {
        Session_ = session;
    }
    public abstract IDomainObject Receive ( int id );
    protected ISession Session {
        get {
            return Session_;
        }
    }
    private readonly ISession Session_;
}

// Класс наследник, которому необходимы особые сервисы сеанса связи.
public class SqlReceiver : Receiver {
    public SqlReceiver ( ISession session ) 
        : base ( session ) {
        if ( !( session is SqlSession ) ) {
            throw new InvalidСastException ( "Invalid session type." );
        }
    }
    public override IDomainObject Receive ( int id ) {
        SqlConnection connection = ( ( SqlSession ) Session ).CreateConnection ( );
    }
}

// Динамическая фабрика, которая создает получатели, 
// для определенного сеанса, причем ей неинтересны детали этого сеанса.
public class ReceiversMounter {
    public ReceiversMounter  ( ISession session ) {
    }
    // Метод конфигурирования фабрики.
    void RegisterReceiver ( int receiverId, Type receiverType ) {
        // Сохранение типа получателя и его идентификатора.
    }
    // Фабричный метод.
    Receiver GetReceiver ( int receiverType ) {
        // Динамическое определение необходимого типа получателя по его id.
        return Activator.CreateInstance ( receiverType, new object [ ] { Session } );
    }
    protected ISession Session {
        get {
            return Session_;
        }
    }
    private readonly ISession Session_;
}


Это сообщение отредактировал(а) adLucem - 4.5.2007, 11:10
PM MAIL ICQ   Вверх
Hurricane
Дата 4.5.2007, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 10.4.2007

Репутация: 3
Всего: 9



Цитата(tol05 @  4.5.2007,  02:33 Найти цитируемый пост)
Методов, добавленных в потомки и требующие вызовов через ссылку базового класса не вижу, а ВЫ?

Э, вот тут ты не прав. adLucem уже привел пару примеров, я добавлю еще от себя - на практике, особенно в больших проектах, довольно часто возникает ситуация, что нельзя модернизировать базовый класс (к тому же он может быть не один), а начиная с какого-то уровня иерархии надо добавить какие-то функциональные возможности. Вносить все в базовый класс не имеет смысла, он про эти новые функции ничего не знает. И не всегда возможно, по разным причинам - это может потребовать огромного количества изменений, этот класс может использоваться в нескольких проектах и внесение изменений в него нежелательно, и др. Хорошо, если удается сделать "промежуточный" базовый класс - унаследовать его от старой иерархии, добавить абстрактные методы, и от этого класса уже делать специализированные классы, а хранить-передавать по ссылке на этот "промежуточный" класс, но это усложнение не всегда оправдано (например, требуется всего один специализированный класс), а главное - мы все равно уже не гарантированы от ненужности проверки типов.

Цитата(adLucem @  4.5.2007,  01:11 Найти цитируемый пост)
Исправленный код (вариант 2)
Более красивый вариант с точки зрения кода (имхо), но с дополнительными затратами на повторяющееся динамическое приведение типов.
Код

foreach ( Param p in ParamList ) {
    if ( p is IntParam ) {
        чего-то там = ReadParam ( p as IntParam ); //вызов ReadParam(IntParam Param)
    } else if ( p is StrParam ) {
        чего-то там = ReadParam ( p as StrParam ); //вызов ReadParam(StrParam Param)
    }
}


Безусловно - код выглядит красивее. Но если в данном случае это реализовано также, как сиплюсплюсное dynamic_cast<> (или IsKindOf( RUNTIME_CLASS( )) ) - накладные расходы на этот вызов очень большие, поэтому стоит пожертвовать красотой в пользу оптимальности и скорости.


PM MAIL   Вверх
tol05
Дата 4.5.2007, 17:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Ничего не понял, Hurricane
Какая связь между сложностями модернизации больших проектов и необходимостью проверять типы? 
Что ты имеешь в виду?  smile 

Это сообщение отредактировал(а) tol05 - 4.5.2007, 17:06


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Vit
Дата 4.5.2007, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

Репутация: 1
Всего: 207



Пошли теоретические изыски. В принципе, ответ был дан culli во втором посте, и как для меня - то ответ исчерпывающий. Огромное спасибо!


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
stab
Дата 5.5.2007, 03:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: 22
Всего: 48



Vit, всегда пожалуйста.


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
mr.DUDA
Дата 5.5.2007, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



adLucem
tol05
Полиморфизм - удобный инструмент для разработчика сложных систем (как и рефлексия). Применения и того и другого в каждом конкретном случае требует от грамотного разработчика анализа - хотя бы минимального - тех pros and cos (преимуществ и недостатков), которые получаются в конкретном случае. Это главное что нужно держать в голове, остальное - детали.


--------------------
user posted image
PM MAIL WWW   Вверх
  
Закрытая темаСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1304 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.