![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Case of для строк
ford © (2010-03-31 17:24:00)Здравствуйте!
в программу передается параметр от которого зависит какая из процедур должна быть выполнена. Значений параметра около десятка.
я сделал следующим образом
if ParamStr(1)='create' then createnewfile(paramstr(2))
else if ParamStr(1)='send' then sendfile(paramstr(2))
else ....
подскажите, можно ли реализовать это как Case of
т.е. примерно так:
Case ParamStr(1) of
'create' : createnewfile(paramstr(2));
'send' : sendfile(paramstr(2));
...
else
...
end;
понятно что Case не работает для строк
но все же :)
(2010-04-02 17:07:00) [1]Удалено модератором
Игорь Шевченко (2010-04-02 16:45:00) [2]oxffff © (02.04.10 16:19) [43]
так вопрос был про строки...
вот в oracle есть case по строкам ;)
oxffff (2010-04-02 16:19:00) [3]
> Игорь Шевченко © (02.04.10 15:42) [42]
> oxffff © (02.04.10 15:35) [40]
>
> if SameText(foo,'FOO') then
> ShowMessage('FOO')
> else if SameText(foo,'BAR') then
> ShowMessage('BAR')
> else
> ShowMessage('Not FOO nor BAR')
>
> Чутка короче получилось ;)
Только с подтипами у Вас дополнительные раздумья будут.
Например Mycase можно написать, чтобы обрабатывал конструкции вида
var a:Tobject;
a:=Tform.create;
case a.classtype of
Tobject: ...
TComponent: ...
TCustomForm: ..
TForm: ... <-выполняется это.
end;
А с if выстраивать порядок сравнения придется программисту. ;)
Игорь Шевченко (2010-04-02 15:42:00) [4]oxffff © (02.04.10 15:35) [40]
if SameText(foo,'FOO') then
ShowMessage('FOO')
else if SameText(foo,'BAR') then
ShowMessage('BAR')
else
ShowMessage('Not FOO nor BAR')
Чутка короче получилось ;)
oxffff (2010-04-02 15:38:00) [5]Повторюсь.
Если у delphi компилятор чуть лучше. то можно было написать так.
with Stuff do
MyCase('2',
[
['4',procedure
begin
showmessage('Option 1');
end],
['2',procedure
begin
showmessage('Option 2');
end]
],procedure
begin
showmessage('Else option');
end);
oxffff (2010-04-02 15:35:00) [6]Ну и естественно обобщенная версия
TPAIRTYPE<T>=record
Value:T;
Proc:TProc;
end;
CaseAnyTypeClassSupport<T>=class
private
class function GetCaseOption(Value:T;Action:TProc):TPAIRTYPE<T>;static;
public
class procedure MyCase(const Value:T;const Pairs:array of TPAIRTYPE<T>;ElseProc:TProc=nil);static;
class property CaseOption[Value:T;Action:TProc]:TPAIRTYPE<T> read GetCaseOption;default;
end;
uses generics.defaults;
class procedure CaseAnyTypeClassSupport<T>.MyCase(const Value:T;const Pairs:array of TPAIRTYPE<T>;ElseProc:TProc=nil);
var Pair:TPAIRTYPE<T>;
Comparer:IComparer<T>;
begin
Comparer:=TComparer<T>.Default;
for Pair in Pairs do
if Comparer.Compare(Value,Pair.Value)=0 then
begin
Pair.Proc();
exit;
end;
if Assigned(ElseProc) then ElseProc();
end;
class function CaseAnyTypeClassSupport<T>.GetCaseOption(Value:T;Action:TProc):TPAIRTYPE<T>;
begin
Result.Value:=Value;
Result.Proc:=action;
end;
procedure TForm2.FormCreate(Sender: TObject);
var Stuff:CaseAnyTypeClassSupport<string>;
begin
Stuff.MyCase('2',
[
Stuff['4',procedure
begin
showmessage('Option 1');
end],
Stuff['2',procedure
begin
showmessage('Option 2');
end]
],procedure
begin
showmessage('Else option');
end);
end;
Anatoly Podgoretsky (2010-04-02 15:15:00) [7]> oxffff (02.04.2010 14:56:37) [37]
Причины конечно были, но они остались в голове идеолога. Да и какая разница, когда case это особая форма it then else if
oxffff (2010-04-02 15:07:00) [8]
> Sha © (02.04.10 13:07) [35]
> > oxffff © (02.04.10 12:28) [34]
> > Не могу найти в интернете, но были какие причины на отсутствие
> case для строк.
>
> Целочисленная оптимизация?
Вроде после прочтения этого.
http://www.delphifeeds.com/go/s/62355
oxffff (2010-04-02 14:56:00) [9]
> Sha © (02.04.10 13:07) [35]
> > oxffff © (02.04.10 12:28) [34]
> > Не могу найти в интернете, но были какие причины на отсутствие
> case для строк.
>
> Целочисленная оптимизация?
Честное слово не помню. Но какое то ощущение осталось.
Пытался найти. Не нашел.
Возможно неоднозначность сравнения например при case sensitive.
То ли unicode. Честное слово не помню.
Dfcz Gegrby (2010-04-02 14:22:00) [10]
> oxffff © (02.04.10 12:02) [30]
Извращенец. (в хорошем смысле ;) )
Sha (2010-04-02 13:07:00) [11]> oxffff © (02.04.10 12:28) [34]
> Не могу найти в интернете, но были какие причины на отсутствие case для строк.
Целочисленная оптимизация?
oxffff (2010-04-02 12:28:00) [12]
> Игорь Шевченко © (02.04.10 12:25) [33]
> oxffff © (02.04.10 12:02) [30]
>
> Круть! Только зачем ?
Отдохнуть от Oracle. И возможно взять некоторые идеи к себе в компилятор.
Не могу найти в интернете, но были какие причины на отсутствие case для строк.
Игорь Шевченко (2010-04-02 12:25:00) [13]oxffff © (02.04.10 12:02) [30]
Круть! Только зачем ?
oxffff (2010-04-02 12:11:00) [14]Поддержка else. :)
procedure MyCase(const Value:string;const Pairs:array of TPair;ElseProc:TProc=nil);
var Pair:TPair;
begin
for Pair in Pairs do if Pair.Value=Value then
begin
Pair.Action();
exit;
end;
ElseProc();
end;
oxffff (2010-04-02 12:03:00) [15]
> здесь он совсем гибок.
не совсем гибок. :)
oxffff (2010-04-02 12:02:00) [16]Решил отдохнуть от Oracle. Написал только что. Сильно не бить.
Идея была свести до использования
MyCase('1',[
['1',procedure
begin
showmessage('Fuck stuff by oxffff. Option 1');
end],
['2',procedure
begin
showmessage('Fuck stuff by oxffff. Option 2');
end]
]);
Но!Есть ограничения у компилятора Delphi, здесь он совсем гибок.
Придется так
MyCase('1',[
self['1',procedure
begin
showmessage('Fuck stuff by oxffff. Option 1');
end],
self['2',procedure
begin
showmessage('Fuck stuff by oxffff. Option 2');
end]
]);
Код
TPair=record
Value:string;
Action:TProc;
end;
TForm2 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
protected
Function GetCaseOption(Value:string;Action:TProc):TPair;
public
{ Public declarations }
property CaseOption[Value:string;Action:TProc]:TPair read GetCaseOption;default;
end;
var
Form2: TForm2;
procedure MyCase(const Value:string;const Pairs:array of TPair);
var Pair:TPair;
begin
for Pair in Pairs do if Pair.Value=Value then
begin
Pair.Action();
exit;
end;
end;
function TForm2.GetCaseOption(Value: string; Action: TProc): TPair;
begin
result.Value:=Value;
result.Action:=action;
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
MyCase('1',[
self['1',procedure
begin
showmessage('Fuck stuff by oxffff. Option 1');
end],
self['2',procedure
begin
showmessage('Fuck stuff by oxffff. Option 2');
end]
]);
end;
Leonid Troyanovsky (2010-04-02 09:48:00) [17]
> _Юрий (01.04.10 19:54) [28]
> Требуется создать дочерний объект нужного класса в зависимости
> от имени узла, и вызвать его загрузку.
Т.е., имена, все же, поступают извне.
Я б обратил внимание на 1 метод by Vladimir Titov.
И еще, тут стоило б подумать об использовании
Delphi streaming system.
--
Regards, LVT.
_Юрий (2010-04-01 19:54:00) [18]
> Leonid Troyanovsky © (31.03.10 22:10) [22]
> Если импорт строк исключен, то мне немного сложно представить
> необходимость их пользования в данном случае.
>
Приведу пример:
грузимся их XML
Начинаем обработку очередного узла
var Node: IXMLNode;
Требуется создать дочерний объект нужного класса в зависимости от имени узла, и вызвать его загрузку.
Как решать задачу...
Можно сделать регистрацию классов, и искать нужный класс в цикле, сравнивая имя Node с результатом какого-нибудь классового виртуального метода общего предка:
for I:=0 to ClassList.Count -1 do
if TMyClass(ClassList[I]).GetXMLNodeName = Node.NodeName then
begin
Result:=TMyClass(ClassList[I]).Create();
...
но если дочерних классов немного, то городить регистрацию может быть нецелесообразно. Кроме того, общего предка может не быть.
Тогда пишем так:
case IndexStr(Node.NodeName, [TMyClass1.GetXMLNodeName, TMyClass2.GetXMLNodeName, TMyClass3.GetXMLNodeName]) of
0: Result:=TMyClass1.Create();
1: Result:=TMyClass2.Create(param1);
2: Result:=TMyClass3.Create(param2, param3);
else NotFound();
то есть сами значения строк могут приходить и снаружи, но именно массив полностью заполняется прямо в теле case
Я правда погорячился, когда сказал, что паттерн используется в хвост и в гриву. Используется он изредка, часто используется другой паттерн, похожий
case IndexOfObject(MyObj, [TMyClass1, TMyClass2, TMyClass2]) of
0: //MyObj is TMyClass1
1: //MyObj is TMyClass2
2: //MyObj is TMyClass3
вместо многократных
if MyObj is TMyClass1 then ...
else if MyObj is TMyClass2...
Но это уже оффтоп.
И на месте автора я бы для данного примера сделал по-другому, а именно - объявил бы тип-перечисление, и завел бы констатарный массив строк.
type
TMyOperation = (moOpen, moSend, moETC);
const
Commands: array[TMyOperation] of string = ('Open', 'Send', 'ETC');
плюсом является то, что при добавлении команды в перечисление компилятор сам подскажет, куда вставить новую строковую константу
ford (2010-04-01 09:26:00) [19]спасибо за предложенные варианты :)
Leonid Troyanovsky (2010-04-01 08:15:00) [20]
> Германн © (01.04.10 01:46) [25]
> У меня была, да и сейчас существует и продаётся (вот только
> вчера-позавчера обновил инсталляторы) ПО, в котором две
> программы обмениваются информацией по TCP/IP.
Если они обмениваются, то у обеих есть импорт (строк).
А тут извне строки не поступают.
Кто там у нас не в теме? :)
--
Regards, LVT.