Тупизмы в C#

 
1 2 3
+
-
edit
 

digger

опытный

Фoрмaльнo warning прaвильный, Бoрлaнд C егo выдaет если oдин из oперaндoв числo. Результaт мoжет не пoместиться в бaйт , нo если взять short ,пoтери цифр не будет - вoт смысл. Если oперaнд long, тo делaть нечегo и warninga нет.
 

Rada

опытный

2 Balancer: а ежели так:
code text
  1. short a, b, c;
  2. b = 5;
  3. c = 10;
  4. a = b + c;


Тогда что будет?
С себя можно начать когда все остальное будет в порядке.  

Balancer

администратор
★★★★☆
Rada>Тогда что будет?[»]

Естественно, то же самое :)
error CS0029: Cannot implicitly convert type 'int' to 'short'

int - наименьший "автоматический" тип.
Словом, запрещены все неявные преобразования, которые могут привести к потере значения.
 

Rada

опытный

>Естественно, то же самое

Тогда слава богу, теперь всё понятно. :)

>int - наименьший "автоматический" тип.

Ты имеешь ввиду - для всяческих целочисленных под-типов (byte, short)?
С себя можно начать когда все остальное будет в порядке.  

Balancer

администратор
★★★★☆
Rada>Ты имеешь ввиду - для всяческих целочисленных под-типов (byte, short)?[»]

Просто там в стандарте жёстко расписаны правила. Выполняются в указанном порядке:
  • (decimal) + (float|double) -> error
  • (decimal) + (any) -> (decimal)
  • (double) + (any) -> (double)
  • (float) + (any) -> (float)
  • (ulong) + (sbyte|short|int|long) -> error
  • (ulong) + (any) -> ulong
  • (long) + (any) -> long
  • (uint) + (sbyte|short|int) -> long
  • (uint) + (any) -> uint
  • все остальные случаи преобразуются к int.


Вот последней строчкой я и имел в виду, что "int - "наимениший" тип". Последнее звено :)
 

Rada

опытный

Ещё интереная особенность - блок не может декларироать локальные имена, если они попадаются в блоках выше.

int i = 0;
...
{
int i = 2; //Error
...
}

Но это - не тупизм, а хорошее решение.
С себя можно начать когда все остальное будет в порядке.  

Fakas

опытный

>>>Гм. Если 5 и 10 - это переменные, то опаньки
TEvg>>Именно. Не 5 и 10, а - A,B,C : BYTE;
Balancer>Если 5 - константа, то и b = 5 - тоже константа. Любой нормальный компилятор должен это учитывать при отпимизации.

Рома, ты не прав :). Раз было объявление :
var A,B,C : byte;
то это переменные, со всеми вытекающими.
А вот что бы были константы,то надо :

var A : byte;
A := 10+10;

Но при этом компайлер не будет мучаться, он на этапе компиляции сложит 10+10, и занесет в А 20.
А вот код типа

var A : byte;
A := 200+200;

Компайлер даже не пропустит — Constant expression violates subrange bounds. И это есть гуууд ;).


Sapienti sat !  

Balancer

администратор
★★★★☆
Rada>Ещё интереная особенность - блок не может декларироать локальные имена, если они попадаются в блоках выше.

Да, меня это тоже добило в своё время. Тут сказать забыл. Глобальные переменные перекрывать нельзя :-/

И старый трюк, когда раньше, если не знаешь, используется уже это имя в данном пространстве имён или нет, просто заключал его использование в { ... } больше не проходит. ИМХО, надёжность кода от этого только упала. Теперь чаще придётся вычитывать чужие куски кода, что не есть правильная идеология.

Rada>Но это - не тупизм, а хорошее решение.[»]

А я - против :D

Fakas>Рома, ты не прав :). Раз было объявление :
Fakas>var A,B,C : byte;
Fakas>то это переменные, со всеми вытекающими.

Если я написал b=5, может ли в разное время в b оказаться разное значение? Нет. Поэтому до первого реального изменения нормальный компилятор учитывает, что значение переменной константное и проводит соответствующую оптимизацию.

Fakas>А вот что бы были константы,то надо :
Fakas>var A : byte;
Fakas>A := 10+10;
Fakas>Но при этом компайлер не будет мучаться, он на этапе компиляции сложит 10+10, и занесет в А 20.

Он итак занесёт 20. Даже при a = b + b :)

code cpp
  1.     int a, b;
  2.     b = 5;
  3.     a = b + b;
  4.     printf("%d", a);


code text
  1.   00000 6a 0a        push    10         ; 0000000aH
  2.   00002 68 00 00 00 00   push    OFFSET FLAT:<string>
  3.   00007 e8 00 00 00 00   call    _printf


Зачем считать при исполнении то, что считается при компилляции?

code cpp
  1.     int sum=0;
  2.     for(int i=1; i<=10; i++)
  3.         sum += i;
  4.     printf("%d", sum);


code text
  1.   00000 6a 37        push    55         ; 00000037H
  2.   00002 68 00 00 00 00   push    OFFSET FLAT:<string>
  3.   00007 e8 00 00 00 00   call    _printf

 

TEvg

аксакал

админ. бан
>Если я написал b=5, может ли в разное время в b оказаться разное значение? Нет. Поэтому до первого реального изменения нормальный компилятор учитывает, что значение переменной константное и проводит соответствующую оптимизацию.

Переменная никак не может быть константой. Компилятор не обязан убирать за программистом-идиотом.
 

Balancer

администратор
★★★★☆
TEvg>Компилятор не обязан убирать за программистом-идиотом.[»]

"Машина должна работать, человек - думать" - © IBM.

Пусть перемножает числа компьютер, а не программист.
 

Mishka

модератор
★★☆
>>Если я написал b=5, может ли в разное время в b оказаться разное значение? Нет. Поэтому до первого реального изменения нормальный компилятор учитывает, что значение переменной константное и проводит соответствующую оптимизацию.
TEvg>Переменная никак не может быть константой. Компилятор не обязан убирать за программистом-идиотом.[»]

Жень, Рома прав. Это нормальная компиляторная оптимизация называемая "константные вычисления". Мы ее и для Алгола 68 делали в 1988, и для Ады. Даже студенты, писавшие компайлер для Модулы 2 под руководством Бокра тоже так делали. Можешь поспрошать Андрея Гниловского - он тоже здесь на форумах - он тоже такие выкрутасы любил.
 
RU Dem_anywhere #01.09.2004 14:40
+
-
edit
 

Dem_anywhere

аксакал

TEvg>Компилятор не обязан убирать за программистом-идиотом.
А он необязательно идиот. Это могут быть, например, глобально определённые символические константы, а в коде просто их использование...
 

Rada

опытный

Rada>Но это - не тупизм, а хорошее решение.
Balancer>А я - против

Ссылаясь во вложенном блоке на переменную - как добраться до той что выше? Я понимаю тот трюк, сам использовал иногда, но всё же? Где ты ещё в статической области встречал два идентичных имени? Вот Це-шарп и устранил эту несуразицу.
С себя можно начать когда все остальное будет в порядке.  

Balancer

администратор
★★★★☆
Rada>Ссылаясь во вложенном блоке на переменную - как добраться до той что выше?

А кто тебя во вложенном блоке заставляет вводить одноимённые переменные? Отмазки, типа случайного совпадения имён не прокатят, т.к. если ты пользуешься внешним именем, то ты его знаешь :)

Rada>Где ты ещё в статической области встречал два идентичных имени?

Ну вот нужно мне цикл организовать. И я не обязан помнить, есть у меня уже переменна i выше уровнем или нет. Засунул внутрь блока и описал там временную переменную i. Это самый распространённый случай в моей практике. В языках без локальных областей видимости мне приходится придумывать переменным цикла заведомо несуразные имена, так, чтобы уменьшить вероятность пересечения. Бред! Я не должен помнить все вышестоящие имена, это нарушает структурность!

Rada>Вот Це-шарп и устранил эту несуразицу.[»]

Вот он и аструктурен в этом смысле :)
 

Rada

опытный

Ну вот нужно мне цикл организовать. И я не обязан помнить, есть у меня уже переменна i выше уровнем или нет. Засунул внутрь блока и описал там временную переменную i. Это самый распространённый случай в моей практике. В языках без локальных областей видимости мне приходится придумывать переменным цикла заведомо несуразные имена, так, чтобы уменьшить вероятность пересечения. Бред! Я не должен помнить все вышестоящие имена, это нарушает структурность!
 


А тебя родители чему учили? Разбивать на функции, коль печёшься о пересечении имён. :) Да и в C# через for each вообще можно без i обойтись.
С себя можно начать когда все остальное будет в порядке.  

Balancer

администратор
★★★★☆
Rada>А тебя родители чему учили? Разбивать на функции, коль печёшься о пересечении имён. :)

Ага, и передавать в функцию, скажем, десяток нужных переменных? Или заводить специальные объекты? Или кучу глобальных переменных? Не проще ли делать локальные области видимости? :)

Rada>Да и в C# через for each вообще можно без i обойтись.[»]

Нельзя. foreach не позволяет менять массив, по которому проходишь. Я уже молчу про то, что далеко не все циклы - работа с массивами :)
 

Vale

Сальсолёт

Вспомню-ка детство... студенческое...
Чем хорош Паскаль - в нём есть локальные функции :)
То, чего до сих пор нет в наследниках С, ЕМНИП.
"Не следуй за большинством на зло, и не решай тяжбы, отступая по большинству от правды" (Исх. 23:2)  

Balancer

администратор
★★★★☆
Vale>То, чего до сих пор нет в наследниках С, ЕМНИП.[»]

Есть во многих :) В том же PHP.
 

Vale

Сальсолёт

Может ещё "Сsh" в наследники Си записать :hilol: ?
Имелось в виду из компилируемых, "нормальных" языков.
"Не следуй за большинством на зло, и не решай тяжбы, отступая по большинству от правды" (Исх. 23:2)  

Balancer

администратор
★★★★☆
Vale>Может ещё "Сsh" в наследники Си записать :hilol: ?
Vale>Имелось в виду из компилируемых, "нормальных" языков.[»]

Дык, PHP давным давно компилируемый. Так что уточняй уж до "компилирующих автономный нативный код" :)
 

Rada

опытный

Vale>Вспомню-ка детство... студенческое...
Vale>Чем хорош Паскаль - в нём есть локальные функции :)
Vale>То, чего до сих пор нет в наследниках С, ЕМНИП.[»]

Локальные функции тут не помогают ничем - из другой оперы.

Balancer>Ага, и передавать в функцию, скажем, десяток нужных переменных? Или заводить специальные объекты? Или кучу глобальных переменных? Не проще ли делать локальные области видимости?

Нет, я про то, что если у тебя всерьез встает проблема столкновений имён, то значит ты многое лепишь в кучу. Я работаю часто на VB 6.0, в котором вообще никаких локальных областей нет - и ни разу не сталкивался с таким аспектом. А трюк с for(int i=0; i < k;i++) делал лишь для своих сдуденческих поделок, когда через 10 минут надо сдавать работу преподу, и нифига не готово.
С себя можно начать когда все остальное будет в порядке.  
+
-
edit
 

Balancer

администратор
★★★★☆
Rada>Нет, я про то, что если у тебя всерьез встает проблема столкновений имён, то значит ты многое лепишь в кучу.

Несколько вложенных циклов - это куча? Скажем, я прохожу по матрице и выполняю достаточно сложную обработку ячеек. Ну, пусть, от балды, это будет генетический алгоритм связной нейросети. И вот мне там надо ещё цикл организовать будет. Мне придётся смотреть, какие переменные цикла я использую выше. А это - неструктурно. Язык должен позволять не заботитсья о таких вещах. C++ - позволяет. C# - нет. Значит на таком уровне в C# задумываться нужно больше. Уровень языка с этой стороны, соответственно, ниже.

Rada>Я работаю часто на VB 6.0, в котором вообще никаких локальных областей нет - и ни разу не сталкивался с таким аспектом.

Задачи, значит, такие. Или ты привык решать их автоматически. Тот, кто забивает микроскопом гвозди тоже может считать искренне, что так лучше и сомневаться в пользе молотка :)
 
+
-
edit
 

Balancer

администратор
★★★★☆
Rada>Локальные функции тут не помогают ничем - из другой оперы.

Ну, здрасьте! Локальные функции - это локальные области видимости. И позволяют спрятаться от перекрывающих переменных и не заботиться о них. Другое дело, что при большом количестве переменных их применение сложно, и, в любом случае, это заметно бОльшая писанина.

Кстати, в самых структурных и высокоуровневых языках, функциональных, обязательно есть Лямбда-исчисление. Более того, оно нынче введено практически во все императивные высокоуровневые языки, пусть, порой, и не очень удачно - те же PHP, Python...
 

Rada

опытный

Да я пожалуй ступил насчёт локальных функций - я имел ввиду что в них также можно перекрывать имена из внешних областей.
С себя можно начать когда все остальное будет в порядке.  
+
-
edit
 

zespri

новичок
Balancer>Несколько вложенных циклов - это куча? Скажем, я прохожу по матрице и выполняю достаточно сложную обработку ячеек. Ну, пусть, от балды, это будет генетический алгоритм связной нейросети. И вот мне там надо ещё цикл организовать будет. Мне придётся смотреть, какие переменные цикла я использую выше. А это - неструктурно. Язык должен позволять не заботитсья о таких вещах. C++ - позволяет. C# - нет. Значит на таком уровне в C# задумываться нужно больше. Уровень языка с этой стороны, соответственно, ниже.

Тут такая штука. Дизайнеры языка должны принимать дизайн дисижны. И тут на всех не угодишь. Есть много вопросов религиозного толка, по поводу которых спорят уже десятки лет. Прична конкретно того решиня следующая, и я думаю, что ты об этом знаешь. В C++ были очень часто трудно отловимые ошибки из-за областей видимости. Скажем переменная с одим именем имеет разный смысл в двух вложенных областях. Когда код мало мальски сложный, и пишется и поддерживается разными людьми высока вероятность ошибки, что человек обратится к перменной во внутренней области видимости имея в виду переменную из внешней области видимости. Что бы исключить возмжность этого класса ошибок введено такое ограничение.
 
1 2 3

в начало страницы | новое
 
Поиск
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru