Click here to Skip to main content
15,888,172 members
Please Sign up or sign in to vote.
2.67/5 (3 votes)
See more:
As per Inheritance Concept we Can not Cast base type to Child type.Here FindControl returns Control object but Still I am able to Covert it into textbox.How this is Possible?Please Clear my Concept?

Please refer this line.

lblName.Text = ((TextBox)web.FindControl("txtName")).Text;

What I have tried:

Class AA
{

}

Class BB : AA
{
}

Class Progarm
{
Static Void Main(string args[])
{
//Inhertiance Concept
BB b=new BB();
(AA)b----This is Possible
AA a=new AA();
a(BB)------This is not Possible

}
}
Posted
Updated 31-Mar-16 5:29am
Comments
Jitesh Hirani 31-Mar-16 7:24am    
What is the error you are facing?
Also say what is the result of 'web.FindControl("txtName")'
vinod 23 31-Mar-16 7:40am    
I am not getting error.Code is running properly but I Just want to clear my concept about Inheritance.
web.FindControl("txtName")-This Method returns "Control" Object which is base Class For Class "TextBox".And Inheritance tells us Base Class Can not be Converted into Child Class using Cast "() " opertaor.But Still I am Able to Conver tControl (Parent of Class TextBox) Object into TextBox(Child of Class Control).How is this Possible?

Imagine your object is like a box with your box being an interface, or type. So I have an Animal class with a NumberOfLegs property. Creating an instance of animal is like having a box and that box is the Animal box, and inside it is NumberOfLegs. All I can do is open that box and examine the contents.

Now let's say I have a Dog class, and dog has a LikesWalkies property, and dog inherits animal. Now I have a box within a box. The outer box is called Dog and contains LikesWalkies and it also contains an Animal box and inside that is NumberOfLegs. When I ask what inside Dog that includes everything inside the boxes that are inside Dog too. So when I say dog.LikesWalkies that is valid as Dog contains that property, when I say dog.NumberOfLegs that is also valid as while Dog doesn't contain that property, it contains a box that does contain that property.

Think about casting as shifting the focus of which box you're interested in.

C#
Dog dog = new Dog();
Dog.LikesWalkies = true;
Dog.NumberOfLegs = 4;

Animal animal = (Animal) dog;



In the code above we can ask dog if it likes walkies and how many legs it has. However with animal we can only ask how many legs, this is because we are looking at the Animal box inside dog. Even though the animal box is inside the dog box, we can't see "outside" animal to its parent properties. Those properties still exist...we just can't see them via the animal casting as the animal casting is only looking at the inner Animal box.

Now let's say I try this

C#
Animal animal = new Animal();
Dog dog = (Dog) animal;



it won't work. When we create an instance of Dog we automatically create an instance of the Animal box inside it so we can cast from Dog to Animal. When we create an Animal box....there is no Dog box around it which is why you can't "cast up", so the above code will throw an exception. After all, Cat could also inherit Animal as could many other classes. When you create the subclass (Animal) it creates no other outer boxes so you can't cast to those.

Now we'll get to your actual question, hopefully you're still with me :)

The Controls collection can contain any box that has a Control box inside it (ie any class that inherits Control). So your Controls collection actually has things like TextBox, Label etc, and each TextBox box and each Label box has a Control box inside it. So when you ask for a textbox via FindControl what you get back is a TextBox box, but the reference isn't pointing to the outer box (TextBox) but the inner box (Control). Although it's the inner box you're looking at, the outer box of TextBox still exists so we can actually "cast up" and shift our focus from the inner Control box to the outer TextBox box and access all of its properties.

So that's kinda what is going on. An object can have many interfaces and you can have a reference to a particular interface on that object, but as long as the object supports other interfaces you can cast to them. When you can't cast to them is when they simply don't support them. A Dog object has a Dog interface but also an Animal interface so we can cast between Dog and Animal, but an Animal object only has an Animal interface so we can't cast from Animal or anything else.

http://s27.postimg.org/bd3gnpoeb/findcontrol.png[^]
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 31-Mar-16 11:35am    
No,
Animal animal = (Animal) dog;
should be
Animal animal = dog;

Both ways will work, but this unneeded cast spoils your whole answer. It's really, really important to understand that assignment of the object of derived type to a variable/member of a base class in not type cast but is the assignment.

I also understand that this is just for illustration
Dog dog = (Dog) animal;

But in general case, it won't work, will through an exception. I'm afraid some readers can consider it as an advice and follow the technique. In real code, this should be even avoided or replaced with dynamic cast.

Please see Solution 4.

—SA
F-ES Sitecore 31-Mar-16 11:53am    
> But in general case, it won't work, will through an exception

That was what I was saying, that it wouldn't work :) but I agree I didn't make that obvious enough so I've updated my post.
Sergey Alexandrovich Kryukov 31-Mar-16 11:56am    
I understand you were saying that and understand what's going on. I did not down-vote it, or something.
I just say it can be confusing...
When I quickly look at the answer, this is what catches my eye. Such fragment should never appear in code as is, in practice; so it should be stressed somehow.
—SA
This isn't specifically related to the class Control or to the FindControl(..) method.

And it's as simple as this: You can cast an object to a specific type if it actually is of that type (or of a compatible type).

If the type of an object has a base-type, you might store that object in a variable that is declared as that base-type because of Polymorphism:
C#
Control ctrl = new TextBox();
// or even:
object o = new TextBox();
At that point you still have a TextBox-object, just that your variable is declared as Control (or object in this example). And that's why you can cast it like this:
C#
TextBox txtBox = (TextBox)ctrl;
// or (respectively):
TextBox txtBox = (TextBox)o;
And it's exactly the same with that FindControl-method: It doesn't return objects of type Control, it returns objects of types that are derived from Control. So you can cast the returned object to the actual type.

Just when you attempt to perform an invalid cast (like casting a Button object returned from FindControl(..) to TextBox) it will fail at runtime. Button and TextBox share the common base-type Control but a Button is not a TextBox.
 
Share this answer
 
v3
Comments
Sergey Alexandrovich Kryukov 31-Mar-16 11:32am    
I think you have to explain what happens if ctrl is not assignment-compatible with TextBox. Generally, you should not do such casts. See also Solution 4.

Your post can confuse the readers and provoke totally unacceptable code which may never work. I understand that this is just the illustration of the idea, but some may consider it as an advice and face troubles.

—SA
Hi Vinod,
Its a very good question, the following answer is based on my knowledge. there might be some other good explanations also.

FindControl Method returns a Control object [ as per the .Net library ]
but during runtime, the Method will return only the Selected Control object ( eg: TextBox ), It wont return the Control Object

Suppose if the FindControl() returns a Control Object and then if you try to cast it to a TextBox, it will throw an error

debug this code and check:
C#
Control ctrlObj = new Control();
 TextBox txt = (TextBox)ctrlObj;



FindControl() Method in .Net Library
C#
// Summary:
       //     Searches the current naming container for a server control with the specified
       //     id parameter.
       //
       // Parameters:
       //   id:
       //     The identifier for the control to be found.
       //
       // Returns:
       //     The specified control, or null if the specified control does not exist.
       [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
       public virtual Control FindControl(string id);


You shall check the type before casting:
C#
var obj = panel11.FindControl("txtName");
         string typeName =  obj.GetType().Name;  // It will result TextBox


Please refer Sergey's answer (Solution 4) for more info on Casting
 
Share this answer
 
v3
Comments
Sergey Alexandrovich Kryukov 31-Mar-16 13:53pm    
TextBox txt = (TextBox)ctrlObj;
is confusing. Some may think that they should really do so, directly and unconditionally, and get into trouble. Please see my comments to other answers.
—SA
Karthik_Mahalingam 31-Mar-16 14:01pm    
Hi Sergey
I agree with your suggestion, since the OP has posted the question with direct casting, so i had thought of casting in his format instead of using as keyword.

I will add reference to your solution# in my solution.
Fist of all, you have to understand why the types of the classes are assignment-compatible when you assign a variable/member of a base class to a reference to an object of a derived class (and this is not conversion at all, this is assignment!), and not visa versa.

This is because the types are extended, not reduced. With down-casting (assigning the reference of a base class to a variable/member of the derived class), you would open access to some added member, which may not exist during runtime. I recently explained it here: Why is explicit casting required?[^].

You have to understand that the type declared as a type of a variable of member is a compile-type type, and when you assign, you play with the runtime type. An actual runtime type can be assignment-compatible with the runtime type on the left of the assignment operator, or not. Note that type casts is a violation of OOP. Normally, you never do casts, only assignments. The runtime types different from the declared type is the base of OOP and, in particular, polymorphism.

However, there are cases when this violation can be practical. It often happens in UI. It happens when, in your OOD, you took into consideration everything but one small thing. And so on. then you have to do the cast and dynamically check up the type before casting. Such dynamic casting is better to do in one shot:
C#
AA aa;
BB bb = aa as BB;
if (bb != null)
   bb.SomeMemberNotExistingInAA();


[EDIT]

Also note that dynamic cast presents considerable performance cost, compared to "pure OOP", including compatible assignment and late binding, the dynamic dispatch via the virtual method call, which should be highly preferred to dynamic casts. Please see also the discussion in comments below.

—SA
 
Share this answer
 
v2
Comments
Sascha Lefèvre 31-Mar-16 13:20pm    
5ed

> Such dynamic casting is better to do in one shot

I somewhere read (IIRC from a trustworthy source) that as is slower than a combination of is and a cast. If you're interested I'll try to dig it up.
Sergey Alexandrovich Kryukov 31-Mar-16 13:49pm    
Oh, good point. I'll need to add an update to my answer: when there is such violation of OOP, it's also involve extra performance cost, considerable to the usual compatible assignment and dynamic dispatch via the virtual. I don't know how "as" compares with "is" though, would be interested to know, too.

Thank you, Sascha.
—SA
Sascha Lefèvre 31-Mar-16 14:40pm    
I found it - but it's actually only true for value types:
http://stackoverflow.com/questions/1583050/performance-surprise-with-as-and-nullable-types
Sascha
Sergey Alexandrovich Kryukov 31-Mar-16 15:52pm    
Thank you, Sascha.
Well, including value types, with its boxing, makes the whole big difference...
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900