Hello, PavliK!
P> Ниже приведен кусок кода на C#
P> Я только приступил к его изучению.
P> Помогите пожалуйста разобраться с конструкцией выделенной жирным.
P> Как то не привычно что скобки стоят перед "о"
P> как читать эту конструкцию и как её понимать, объясните пожалуйста.
P> public override bool Equals (object o)
P> {
P> // Совпадают ли у объекта, принимаемого в качестве параметра, //
P> значения переменных с моими?
P> Person temp = (Person)o;
Это приведение типа. параметр типа object приводится к твоему типу Person.
В С# два способа приведения типа первый как ты написал. В этом случае если переменную не удастся привести к указанному в скобках типу то возникнет исключение.
Второй способ
Person temp = o as Person;
В этом случае исключения не будет просто переменная temp будет равна null.
О том в каких случаюх каким способом пользоваться написано в журнале RSDN 2004.3
http://rsdn.ru/?article/mag/200403/AsIs.xmlАвтор(ы): Владислав Чистяков (VladD2)
Дата: 05.08.2004
Работая над открытыми проектами, автор заметил, что операторы as и is многими программистами зачастую используются ненадлежащим образом. Результатом очередного двухчасового поиска ошибки и стала эта статья.
Если ты не знаешь что такое приведение типа то всеж лучше купить книжку по C#. Поищи по форуму тут кидали ссылки на достойные книжки по эхотагу.
WBR, Igor Evgrafov.
Posted via RSDN NNTP Server 1.9 beta
Здравствуйте, PavliK, Вы писали:
PK>class Person
PK>{
PK>...
PK> public override bool Equals (object o)
PK> {
PK> // Совпадают ли у объекта, принимаемого в качестве параметра, // значения переменных с моими?
PK> Person temp = (Person)o;
Да. Здесь имеет место переопределения метода Equals типа object. Он в качестве параметра принимает object.
Цитата из Рихтера:
При разработке программ часто прибегают к приведению объекта к другим типам. CLR разрешает привести тип объекта к его собственному типу или любому из его базовых типов. Каждый язык программирования по-своему осуществляет приведение типов. Например, в С# нет специального синтаксиса для приведения типа объекта к его базовому типу, поскольку такое приведение считается безопасным неявным преобразованием. Однако для приведения типа к производному от него типу разработчик на C# должен ввести операцию явного преобразования типов — неявное преобразование приведет к ошибке.
Ну и стоит еще добавить, что все объекты в .NET — производные от System.Object.
Здравствуйте, PavliK, Вы писали:
PK>До этого изучал и работал на PHP, но ООП не применял... всё как то обходился процедурами и функциями
Ну, вот. А тут на Васкик все наезжают.
ЗЫ
ООП тут не причем. Приведение типов есть и в Паскле, и в С.
... << RSDN@Home 1.1.4 beta 2 >>
Здравствуйте, GarryIV, Вы писали:
GIV>В С# два способа приведения типа первый как ты написал. В этом случае если переменную не удастся привести к указанному в скобках типу то возникнет исключение.
private static void ObsoleteMethod(object o)
{
Form form = (Form)o; // По идее, тут должно было упасть, ибо ListBox не может привестись к Form.
form.Show();
}
ListBox control = null; // каким то образом ссылка обнулилась.
ObsoleteMethod(control);
Упадет по NullReferenceException. Так что не такой уж и универсальный оператор ().
Здравствуйте, PavliK, Вы писали:
PK>class Person
PK>{
PK>...
PK> public override bool Equals (object o)
PK> {
PK> // Совпадают ли у объекта, принимаемого в качестве параметра, // значения переменных с моими?
PK> Person temp = (Person)o;
PK> if (temp.firstName = = this.firstName &&
PK> temp.lastName = = this.lastName &&
PK> temp.SSN = = this.SSN &&
PK> temp.age = = this.age)
PK> return true;
PK> else
PK> return false;
PK> }
PK>...
PK>}
Всё очень просто! Допустим имеется класс "Банан". И нужно сравнить его с каким-то другим фруктом.
class Банан
{
public override bool Equals( Фрукт o )
{
try
{
// Фрукт не обязательно является бананом, поэтому может
// возникнуть исключение при преведении типов
Банан temp = (Банан) o;
// далее логика сравнения...
return true;
}
catch
{
return false;
}
}
}
Аналогично можно заменить Фрукт на object, а банан на Person...
Здравствуйте, vguzev, Вы писали:
class Банан
{
public override bool Equals( Фрукт o )
{
try
{
// Фрукт не обязательно является бананом, поэтому может
// возникнуть исключение при преведении типов
Банан temp = (Банан) o;
// далее логика сравнения...
return true;
}
catch
{
return false;
}
}
}
Мой вам совет, избегайте таких конструкций с try{}catch{} потому что:
— теряется производительность;
— тестирование становится невыносимым;
— вы перехватываете все исключения(а если брошено исключение о переполнении памяти, а вы его игнорируете — нехорошо);
— да и вообще так не принято делать.
Гораздо красивее смотриться так:
class Банан
{
public override bool Equals( Фрукт o )
{
if(object.ReferenseEquals(this, o))
return true;
Фрукт k = o as Фрукт;
if(k!=null)
{
...
}
return false;
}
}
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Хотя приведение типов не есть атрибут исключительно ООП, но автор топика верно указывает на главную свою проблему в С# — без знания ООП, имея опыт в небольших компактных PHP — скриптах с динамической типизацией и т.п. сложно понять почти ЛЮБЫЕ конструкции C#,C++ или скажем Delphi. Так как надо перестроить все свое сознание иначе непонятно, зачем вообще классы, все воспринимается громоздким и нелепым. Поэтому если хотеть писать работоспособные программы под .NET. Если ты вообще специалист то стоит внимательно изучить устройство исполняемой среды, почитать IL-код, просмотреть всю библиотеку классов ядра и приложенных библиотек, предварительно прочитав книгу по ООП, как оно связано со структурным и функцимональным программированием и т.д. Если же (без обид) квалификации не хватает и всякие термины только пугают, то лучше для начала узнать как можно в C# быстро сформировать процедурно-подобную программу без всяких модулей и клссов, попробовать в этой структуре по-программировать, привыкнуть к языку и потом уже, когда синтаксис таких элементарных действий как приведение типа не будет напрягать, переходить к нормальному ООП программипрованию.
Для эмуляции 1-проходной процедуры, скрипта так сказать, можно используйте такой шаблон, который надо компилировать в консольное приложение — это не самый элементарный вариант, но и не сложный (комментарии, понятно можно убрать)
Кстати подобную обработку исключений (как я тут привел) в свете приведенных выше соображений тоже можно либо вообще убрать дибо существенно подправить
using System; //доступ к именам базовых классов (не путать с импортированием библиотеки System.dll, using это т.с. "импорт пространства имен")
using System.Collections; //тут есть такие "родные" для любого скриптописателя классы как Hashtable,ArrayList и т.д.
using System.IO; //файловый и иной потоковый ввод-вывод, базовые операции в файловой системе
using System.Text; //кодировки, эффективня работа со строками
using System.Text.RegularExpressions; //собственно регулярные выражения, архитектура ближе всего к Perl
/*то, что мы написали в USING никак не влияет на логику программы и нужно компилятору. Например полное имя класса Hashtable это System.Collections.Hashtable, чтобы первую префиксную часть (протранство имен)не писать каждый раз, мы ее выносим в using, если же короткие имена в каких-то пространствах совпадут — это легко разрешается через псевдонимы классов либо через собственно их полное именование*/
//определяем пространство имен
namespace I.Learn.CSharp
{
//определяем класс, инкапсулирующий логику наше ПРОЦЕДУРЫ
public class ProceduralLikeProgram
{
/*определяем точку входа программы — форма традиционный для винды — процесс принимает аргументы командной строки и возвращает код результата выполнения в виде целого числа*/
public static int Main(string[] arguments)
{
try //попробуем...
{
//запустить и вернуть результат нашей главной ПРОЦЕДУРЫ...
return MainProgramLogic(arguments)
}
//А вдруг случится ОБЛОМ(oblom)...
catch(Exception oblom)
{
//Ну напечатаем про него и вернем, что мол так и так — ошибка (-1)
writeln(oblom);//вызов дополнительного метода, описан ниже
return -1;
}
}
static int MainProgramLogic(string args)
{
//Именно сюда бодяжится собственно процедура, положим программа умножения двух чисел (чем не процедурный скрипт):
write("Введите первое число: ");
int first = inputInt();
write("Введите второе число: ");
int second = inputInt();
writeln("{0} x {1} = {2}",first,second,first*second);
return 0; //самый простой вариант просто вернуть 0
}
//методы для удобства, в .NET поддерживается автоматическая ПЕРЕЗАГРУЗКА (overloadng) функций
//считываем с консоли пользовательский ввод
//строки
static string input()
{
return Console.ReadLine();
}
//простые числа
static int inputInt()
{
return int.Parse(input());
}
//вещественные числа
static float inputFloat()
{
return float.Parse(input());
}
//да-нет
static bool inputBool()
{
string subresult = input();
switch(char.ToUpper(subresult[0]))
{
case 'Y':goto case 'Д';
case 'T':goto case 'Д';
case '1':goto case 'Д';
case 'N':goto case 'Н';
case 'F':goto case 'Н';
case '0':goto case 'Н';
case 'Д':return true;
case 'Н':return false;
default :return false;
}
}
//просто выводит на консоль преообразованный к строке объект
static void write(object what_to_write)
{
Console.Write(what_to_write.ToString());//любой объект наследуется от Object и заведомо имеет метод ToString()
}
//в этой форме вызова использует подстановку объектов в шаблоны, например write("{0} = {1}","2+2",4); выведет: 2+2 = 4
static void write(string pattern,params object[] arguments)
{
Console.Write(string.Format(pattern,(object[]) arguments));/*сюрприз, базовый класс String уже содержит такую функциональность, прямо приводить arguments к object[] потребовалось для того, чтобы он его использовал именно как аргумент-масив, а не как первый элемент аргумента-массива*/
}
static void writeln(object what_to_write)
{
Console.WriteLine(what_to_write.ToString());//любой объект наследуется от Object и заведомо имеет метод ToString()
static void writeln(string pattern,params object[] arguments)
{
Console.WriteLine(string.Format(pattern,(object[]) arguments));
}}
}
данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение