2012-01-20 2 views
0

Я хотел бы сделать что-то вроде этого диез:Non Static/Постоянные значения в случае заявления в пределах коммутатора

int i = 0; 
foreach (Item item in _Items) 
{ 
    foreach (Field theField in doc.Form.Fields) 
    { 
     switch (theField.Name) 
     { 
      case "Num" + i++.ToString(): // Number of Packages 
       theField.Value = string.Empty; 
       break; 
     } 
    } 
} 

У меня есть 20 или около того поля, названные Num1, Num2 и т.д. Если я могу сделайте это все в одном выражении/блоке, я бы предпочел сделать это.

Но компилятор жалуется, что операторы case должны быть постоянными. Есть ли способ использовать динамические переменные в аргументе case, чтобы я мог избежать повторения кода?

Я просто подумал, что я хотел бы упомянуть, целью этого метода является заполнение полей в форме PDF, с соглашениями об именах, которые я не могу контролировать. Есть 20 строк полей с именами типа «Num1» - «Num20». Вот почему конкатенация строк была бы полезной в моем сценарии.

+0

Причина, по которой вы не можете обсуждать (обсуждать?) В [ограничениях на использование операторов C# - почему?] (Http://stackoverflow.com/questions/44905/c-sharp-switch-statement-limitations-why) Я думаю, [этот ответ] (http://stackoverflow.com/a/45584/516797) подводит итог. –

+0

Вы уверены, что не хотите 'i ++' за пределами внутреннего' foreach'? – TrueWill

+0

Ограничение на замещение оператора C# сообщение отвечает на мой вопрос отлично. Большое спасибо! – nocarrier

ответ

9

№ Это просто часть языка. Если значения не являются константами, вам нужно будет использовать if/else if или аналогичное решение. (Если бы мы знали более подробную информацию о том, чего вы пытались достичь, мы сможем дать более подробную информацию об этом решении.)

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

+0

Прежде всего, я полностью удостоен чести получить от вас ответ Джон. Я только что купил C# в Depth Second Edition и, наконец, чувствую, что перехожу к тому, чтобы стать посредственным разработчиком (обладающим достаточным знанием, чтобы быть опасным) для настоящего профессионала. Удивительная книга! Я испытываю полный страх за вашу кажущуюся любовь к взаимодействию среды выполнения .NET, C#, и я искренне ценю вашу страсть./end gushing комментарии. Благодаря! – nocarrier

+0

Я просто хочу быстро добавить - для тех, кто читает это, я не могу уделять достаточное внимание тому, насколько велика C# In Depth. Просто нет ничего подобного - единственная книга, которую я могу сравнить с качеством авторства, - это «JavaScript - хорошие детали» Дугласа Крокфорда. – nocarrier

+0

@Shawn: Ты очень добрый :) Надеюсь, этот ответ был действительно полезен и для решения вашей проблемы, конечно ... –

0

Как насчет:

int i = 0; 
foreach (Item item in _Items) 
    doc.Form.Fields.First(f=>f.Name == "Num" + i++.ToString()).Value = string.Empty; 

Не уверен, что цель пункта в вашем коде, хотя.

+0

'First' будет вызывать исключение, если не найдены соответствующие элементы. – TrueWill

+0

@Krizz Если я что-то не хватает, он делает то, что пытался сделать псевдокод в OP. Что с этим не так? –

+0

@TrueWill Да, но я не знаю, что он хочет делать, если поле не найдено. Я оставил это ему. –

1

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

foreach (Field theField in doc.Form.Fields) 
{ 
    if(theField.Name == ("Num" + i++)) 
    { 
     theField.Value = string.Empty; 
    } 
} 
0

Нет. Нет способа.

Как о замене выключателя с:

if (theField.Name.StartsWith("Num")) 
    theField.Value = string.Empty; 

или какой-либо аналогичный тест?

0
var matchingFields = 
    from item in _Items 
    join field in doc.Form.Fields 
     on "Num" + item.PackageCount equals field.Name 
    select field; 

foreach (var field in matchingFields) 
{ 
    field.Value = string.Empty; 
} 

Для большей эффективности включает в себя DistinctBy на поле Имени после получения подходящих полей (от MoreLINQ или эквивалента).

0

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

Таким образом, вместо того, чтобы писать так:

"Num" + i++.ToString() 

Рассматривают писать так:

string.Format("{0}{1}", "Num", i++.ToString()); 

Кроме того, вы можете рассмотреть вопрос о создании строки, как «Num» в отдельный класс констант.Наличие строковых констант в вашем коде может привести к жесткости программы и ограничить гибкость программы с течением времени по мере роста вашей программы.

Таким образом, вы могли бы иметь что-то вроде этого в начале программы:

using SysConst = MyNamespace.Constants.SystemConstants; 

Тогда ваш код будет выглядеть следующим образом:

string.Format("{0}{1}", SysConst.Num, i++.ToString()); 

А в классе SystemConstants, вы бы что-то вроде этого:

/// <summary>System Constants</summary> 
public static class SystemConstants 
{ 
    /// <summary>The Num string.</summary> 
    public static readonly string Num = @"Num"; 
} 

Таким образом, если вам нужно использовать строку «Num» в любом месте в ваша программа, то вы можете просто использовать «SysConst.Num»

Кроме того, в любое время, когда вы решите изменить «Num» на «Number», скажем, по просьбе клиента, тогда вам нужно только его изменить место, а не большую замену в вашей системе.