· Если текущий документ не выставлен на default-принтер, то переменная defaultPrinterName будет = "".
Замените рассмотренное выше словоблудие на код, приведенный ниже, и вы получите правильный результат, причем прочесть (и выполнить) его значительно проще. Вместо массы ненужных переменных (объявленных a la Pascal) введены новые, которые действительно повышают performance, так устраняют дублирование операций.
void ShowPrinters()
{
PrinterSettings setting = printDoc.PrinterSettings;
string docPrinter = setting.PrinterName, info = "";
PrinterSettings.StringCollection printers = PrinterSettings.InstalledPrinters;
for (int i = 0; i < printers.Count; i++)
{
setting.PrinterName = printers[i]; // По очереди примеряем все принтеры
info += printers[i] +
"\nIsValid = " + setting.IsValid +
"\nIsDefault = " + (printers[i] == docPrinter).ToString() +
"\nPrintToFile = " + setting.PrintToFile + "\n\n";
}
MessageBox.Show (info,"Printers");
}
Еще один фрагмент из того же источника, приведенный без купюр. Там он иллюстрирует идею. По мнению авторов смысл переменных должен быть очевиден. Это так, но какова область действия и время жизни?
while (CurrentLine < LinesPerPage)
{
TextLine = StreamToPrint.ReadLine();
if(TextLine == null)
{
break;
}
// set the vertical position on the page based
// on the current line number
VerticalPosition = TopMargin + CurrentLine * MyFont.GetHeight(e.Graphics);
// draw the text on the page
e.Graphics.DrawString(TextLine, MyFont, MyBrush, HorizontalPosition, VerticalPosition);
// increment the line number
CurrentLine += 1;
}
Вопросы: CurrentLine — это переменная класса или локальная (временная)? TextLine — (очевидно) локальная переменная, но где она объявлена? Как долго живет? Где объявлены VerticalPosition и HorizontalPosition? Объектом какого класса является StreamToPrint? Похоже, что FileStream. Но у всех классов из иерархии Stream нет метода ReadLine! Оказалось, что это объект класса StremReader, то есть, почти из другой оперы. Теперь поразмыслим.
· Вычислять в цикле то, что от него не зависит, — не только расточительство, но и признак лени или слабого ума (см. оператор: MyFont.GetHeight(e.Graphics). Он расположен внутри тела цикла).
· Очевидное правило: выносите за цикл все, что можно из него вынести.
· Если присутствует код подготовки к циклу и код, изменяющий переменные управления циклом (а они здесь присутствуют), то надо использовать цикл for (и только for). Все другие решения — плохой стиль.
· Логика цикла должна быть ясна из его заголовка, каким бы сложным он не был (постулат Кернигана и Ритчи).
· Если программист испытывает затруднения при анализе сложного заголовка цикла, ему надо тренироваться.
· Если логика цикла размыта (переменные, управляющие им, разбросаны, не сосредоточены в одном месте), то это провоцирует ошибки, такой код ненадежен.
· Все переменные должны использовать Camel-notation (начинаться со строчной буквы), иначе их трудно отличить от имен классов, особенно, в случае, если классы имеют статические данные или методы (см. MSDN).
· Если можно обойтись без break, сделай это.
· Чем уже область действия переменной, тем меньше места она должна занимать в серых клеточках того, кто анализирует код. Вывод: тем короче должно быть имя такой переменной.
· Временные переменные не должны требовать от вас усилий, их имена как бы говорят читателю: "Это — ерунда, жди результата". Наоборот, имена переменных класса должны нести смысл (printDoc, myFont и т.д.).
· Большинство программистов заканчивали приличные ВУЗы и, поэтому, привыкли к математической нотации (i, j, k — временные индексы, n — number). Если переменная типа double живет недолго, ее смысл неважен — назовите ее d. Временную переменную типа float назовите коротко — f,
Новую версию фрагмента оформим в виде реакции на событие PrintPage компонента printDoc.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.