We help IT Professionals succeed at work.

Casting question

asi asked
Medium Priority
Last Modified: 2012-05-04
can i Make a casting on parameter (in function) like Sender:Tobject
and According to the ClassName method
Cast the Sender to that object ?
Watch Question



to make the question more clear

> the sender can be 10000 type of object in a different type , the common between all thos objects is (just) that they have property named abcd , i cant start ask 10000 condition and just then make an cast ...

Is this what you are looking for...

procedure TForm1.FormClick(Sender: TObject);
var i : Integer;
   for i := 0 to ComponentCount - 1 do
        if TButton(Components[i]).ClassName = 'TButton' then
          TButton(Components[i]).caption:= Inttostr(i);

.if it isn't ...well...

Viktor Ivanov


what i"m looking for is
MyFunc (Sender:tobject);
CName: String
  CName :=Sender.ClassName;
 with CName(Sender) do
// i.e. to make casting to the sender according to CName
// again the sender can be  from 1000000 object type
// so i can not do like u said if  ... then ...CAST


10x anyway

It is not practical to test 1000 cases of the classname and then cast the object accordingly. I don't think there is anything thing function like ConvertToTypeByNameOf( 'tButton', sender).

But why you want to do that? What is the actual problem that lead you think of doing this? Can virtual type of component solve the problem?


Surely you don't need to know exactly what the component is if it's not one of the classes you're interested in you can just ignore it, or throw an exception or whatever. That then makes it practical to use a case statement (with some sort of function to convert your string classname into an ordinal that a case can deal with)


  cnUnknown : integer = -1;
  cnButton : integer = 1;
  cnPanel : integer = 2;
// etc

function ClassNameToInt(ClassName : string) : integer
  if ClassName = 'tButton' then
      ClassNameToInt := cnButton
  else if ClassName = 'tPanel' then
      ClassNameToInt := cnPanel
    ClassNameToInt := cnUnknown;

function thingy(Sender : tObject)

  button : tButton;
  panel : tPanel;

  // do something
  case ClassNameToInt(Sender) of
    cnButton : button := Sender as tButton;
    cnPanel : panel := Sender as tPanel;
    raise EOhBuggerSomethingWentWrong.Create('unknown sender class');
   // do something else

Good luck,


Delphi is a strongly typed language. That is the reason that what you are trying to do is not possible. The compiler wants to know the type of object is within the WITH clause otherwise it will not compile.

If Delphi would not have been "type-safe", for example the following would be possible to compile but would give erroneous code:

procedure SetControlCaption(Sender : TObject);
  with TObject.ClassType(Sender) do
     Caption := 'Hello there';

Now if Sender would be a TParam (which has no caption) the program would compile but not run. That is the reason why it is not permitted in Delphi.

A good way of handling this are described above. The case statement is often used for that or a nested if construction.

Another good thing is to use base types. For example TWinControl or TControl. You can cast any object derived from TControl to TControl and access the properties and methods of a TControl.

If you want to set the Caption property of all possible classes that have such a property you could use the TypInfo unit to check if the class has a certain property and then set it using functions/procedures in the TypInfo unit.

Functions of interest in TypInfo are:


(If you want an example on how to do this, let me know)

Let us know what you want exactly.

Regards Jacco
Unlock this solution and get a sample of our free trial.
(No credit card required)

can I just add my thanks for pointing out that property! I'd seen it before but hadn't thought of how to use it; I like the idea of storing references in tags :)

I did have a thought though, ClassType returns a tClass (according to the D2 docs) which is the ultimate ancestor of all classes so you're really back at the start again. You've got an object, stored as an abstract ancestor (tClass rather than tObject in this case,) but you've still got to cast it to something if you want to get at any methods not defined by tClass (ie, just about anything.) I think the whole crux of the matter is that you can't write the code blind (unless you really like n-thousand case statements,) you have to know what you want and expect the object to be.

good luck, and thanks again for pointing that one out... Now, where to use it :)


"my menus were very flexible and could even handle and instatiate types that didn't exist when the units were compiled"

Interesting. I also want to know how did you do that. For one of my project, I need to create record structure at run time. May be your code would help.

Hello all :-)

Sorry, but this week's so busy I didn't get around to digging out that old code... I will (almost :-) definitely have the time to post something tomorrow, maybe even today.

AJFleming got me thinking, though... and he has a good point with his statements about TClass... the problem is not so much runtime-behavior as compiler-problems... If you really don't have ANY idea what you're getting, any code like SomeNiftyCasting(Sender).abcd won't compile without problems because the compiler doesn't know if the sender even HAS that property... compilers like translating all "symbolic information" (such as the NAMES of the properties) to addresses - absolute or relative (to the object's base address).

So what if you have these two classes:


How would the compiler know about the relative address of "weight"? Trying to access a field of the same name in two completely unrelated classes would be terrible programming style... nothing (or at least not so much) against Visual Basic, but I think that's the language for doing that kind of stuff... any interpreted language (e.g. JavaScript) can do those things, but a highly (?) optimizing compiler normally won't!

Now did I write complete nonsense and made wrong promises? No, not quite - I just assumed proper programming style and my approach still gives you a lot of flexibility. The thing is that I didn't have to access the properties of completely unknown classes, I just needed to instantiate them without caring too much about the type (return them as a TObject...).

So for the specific question asked here, we're back to my first comment:
"1) How do you know that all the objects that could be passed in sender have property abcd in common? Do they have a common ancestor? In that case, you can easily cast to that ancestor and check the component, e.g. TComponent(Sender).Owner:=Self;"

ASI: Please answer this one before I post a code snippet:
How can you be absolutely sure that the sender will always have a property named abcd?? In "normal" abject oriented programming, the reason is (or at least definitely should be) a common ancestor, e.g. the sender could be any Control and you know that they all have a property "Left". Even if they descend from two ancestors, it wouldn't be so bad - you can check for that... If all those classes are completely independent from each other, something is definitely very wrong with your code...

Let me know and I'll try to post a solution for you later today or tomorrow...
Hello asi?? I can't post a complete solution if you don't answer my questions...

For everybody else who's waiting for some tricks *g*
Oh boy... it's always more complicated than it looks to get some working code out of a project. Of course the code that's needed for a "demo" is in at least 5 different procedures :-(

But I'll try... this was for implementing different optimization algorithms that could be switched at runtime. Code first, explanation below...

In the Form.Create, I do this:
  miRandomFit.Tag    :=integer(TRandomFit);     {this puts me on the }
  miFirstFit.Tag     :=integer(TFirstFit);      {"safe" side: I don't}
  miBestFit.Tag      :=integer(TBestFit);       {know if this value is}
  miPlanningAhead.Tag:=integer(TPlanningAhead); {and will remain constant}

in the "CheckMenuItem", I do this:
  E.StrategyType:=TClass((Sender AS TMenuItem).Tag);  {setting strategy}

where StrategyType is a Property of type TClass
PROCEDURE SetStrategyType(NewType:TClass);
  IF (Strategy=NIL) OR (NewType<>StrategyType) THEN Strategy:=(NewType.Create AS TStrategy); //SetStrategy takes care of disposing old strategy

Section [1] initializes the tags to the integer representation of the Classes! Note how a TYPE can be cast to an integer!!!

Section [2] takes the tag that was assigned to the MenuItem and converts it back to a class. This "class" is assigned to the property Strategytype

which, in the SetStrategyType, instantiates an "object" of the class (note this: NewType.Create; !) and assigns it to the "Strategy-property". The object is cast to the appropriate type by (Newtype.Create AS TStrategy);

Any questions?? I'm afraid it sounds more complicated than it is, but it's hard to explain...
Basically, the whole trick could be done by
NewStrateyObject:= (TClass((Sender AS TMenuItem).Tag).Create) AS TStrategy;

I hope you like this code snippet, although it's off-topic and maybe not soo helpful for asi.

asi: Please answer my questions above so I can post some code that works for you!

If anybody has any questions: Go ahead *g* - this is not about those 30 points anyway... BUT I'm rather busy and might be a bit slow :-(
ok, great...
take a look at my profile and you'll know why I won't answer another question for asi!

I really don't care so much about points any more - that's why I answer questions for just 30 points or even no points at all - but I DO care about my grades and don't like ruining my profile for some lousy points!

Still: If anybody has any questions - go ahead!



sorry , The question u answer was very comprehensive and they are deserve more point !
if u have any idea how can i upgrade your mark & point please tell me about it

man while
please , be happy

Asi :)

well, first of all: You can NOT upgrade the mark and that's the problem - you COULD give me some extra points by asking a "fake" question exclusively for me, but as I said, that's not what I am/was mad about.

I invest some time to help other people (I can't buy anything for those points, you know) and I'd like them to appreciate the help, that's all... (and that includes assigning a grade).

So, I don't really feel that I have solved your problem because I didn't have all the information I needed. If you still want it to be solved, you should answer the questions I asked about 4 weeks ago (July 31st)!


hey holger !

your question was
"1) How do you know that all the objects that could be passed in sender have
     property abcd in common? Do they have a common ancestor? In that case, you
     can easily cast to that ancestor and check the component, e.g.
the story was like that i had a few object some was override on Tlist and Some just from Tobject etc...
after some time i want to add for each ot thos object property named "abcd"
thos objects might be pass  to some function that KNOW (by default- i.e. that thos object parameter that this function recive has object with "abcd" property )
i knew ofcours that i can make common ancestor , but since thos object was based on different "parent" such a task was too much long ...
since i was under time presure , i finaly made this changes and the above question was very much intresting me , theoreticly;
hope i unsewer your question
one more thins i add a fack quetioin named/title "abcd" u may answer your next question there and i'll give u the grade
10x in advance
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.