473,322 Members | 1,911 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

Mixing abstract and template inheritance

Can someone explain to me why I get a compiler error with the
following code on the line obj.DoSomething()?
but if cast the object I get no error. The error I get is:
Cannot access protected member
'GenericDerivedClassTest.Base.DoSomething()' via a qualifier of type
'GenericDerivedClassTest.Base'; the qualifier must be of type
'GenericDerivedClassTest.TBase<DerivedType>' (or derived from it)

Why does it believe the object has to derive from TBase<DerivedType>?
when all it needs to do is derive from Base since that's where the
method is and that's also what TBase<DerivedTypederives from.

It seems to me that the compiler is confused because generics are kind
of like templates/macros and maybe doesn't know how to really traverse
the inheritance hierarchy in all cases?

here's the code:
/// <summary>
/// Templated absract class
/// </summary>
/// <typeparam name="DerivedType"></typeparam>
public abstract class TBase<DerivedType: Base
where DerivedType : TBase<DerivedType>, new()
{
public TBase()
{
}

public static DerivedType StaticDoSomething()
{
// Create a new derived class type
Base obj = (Base)(new DerivedType());

// Let the base class first do something to the object
StaticDoSomethingImpl(ref obj);

// Call the derived class
#if true // This yields the error "Cannot access protected
member..."
obj.DoSomething();
#else // This works fine
TBase<DerivedTypeobj2 = (TBase<DerivedType>)obj;
obj2.DoSomething();
#endif

return (DerivedType)obj;
}
}

/// <summary>
/// Abstract base class
/// </summary>
public abstract class Base
{
public Base()
{
}

public static void StaticDoSomethingImpl(ref Base obj)
{
// Do something to obj
}

protected abstract void DoSomething();
}
Jun 27 '08 #1
4 2941
On Jun 12, 12:06*pm, Israel <israeldip...@hotmail.comwrote:
Can someone explain to me why I get a compiler error with the
following code on the line obj.DoSomething()?
but if cast the object I get no error. *The error I get is:
Cannot access protected member
'GenericDerivedClassTest.Base.DoSomething()' via a qualifier of type
'GenericDerivedClassTest.Base'; the qualifier must be of type
'GenericDerivedClassTest.TBase<DerivedType>' (or derived from it)

Why does it believe the object has to derive from TBase<DerivedType>?
when all it needs to do is derive from Base since that's where the
method is and that's also what TBase<DerivedTypederives from.

It seems to me that the compiler is confused because generics are kind
of like templates/macros and maybe doesn't know how to really traverse
the inheritance hierarchy in all cases?

here's the code:
/// <summary>
/// Templated absract class
/// </summary>
/// <typeparam name="DerivedType"></typeparam>
public abstract class TBase<DerivedType: Base
* * where DerivedType : TBase<DerivedType>, new()
{
* * public TBase()
* * {
* * }

* * public static DerivedType StaticDoSomething()
* * {
* * * * // Create a new derived class type
* * * * Base obj = (Base)(new DerivedType());

* * * * // Let the base class first do something to the object
* * * * StaticDoSomethingImpl(ref obj);

* * * * // Call the derived class
#if true * *// This yields the error "Cannot access protected
member..."
* * * * obj.DoSomething();
#else * * * // This works fine
* * * * TBase<DerivedTypeobj2 = (TBase<DerivedType>)obj;
* * * * obj2.DoSomething();
#endif

* * * * return (DerivedType)obj;
* * }

}

/// <summary>
/// Abstract base class
/// </summary>
public abstract class Base
{
* * public Base()
* * {
* * }

* * public static void StaticDoSomethingImpl(ref Base obj)
* * {
* * * * // Do something to obj
* * }

* * protected abstract void DoSomething();

}- Hide quoted text -

- Show quoted text -
Curious. Why do you have to cast to Base, if your DerivedType is a
Base type? Why this:

Base obj = (Base)(new DerivedType());

Instead of

Base obj = new DerivedType();

Sorry. I know that's not what you asked. I am learning, trying to
understand.
Jun 27 '08 #2
On Jun 12, 5:06 pm, Israel <israeldip...@hotmail.comwrote:
Can someone explain to me why I get a compiler error with the
following code on the line obj.DoSomething()?
It's worth getting rid of generics from the equation to start with -
they're irrelevant here. Likewise you don't need to have any abstract
classes. The issue is to do with your understanding of the "protected"
access modifier. Here's a simpler example:

class Base
{
protected void Foo() { }
}

class Derived : Base
{
public void CallFoo(Base b)
{
b.Foo();
}
}

class Other : Base {}

You'll see the same error message. "protected" doesn't mean "can be
called by any derived type on any instance of the base class". It
means "can be called by any derived type on any instance *of the same
type* (including instances of further derived types)".

So Derived can call Foo on any Derived, but not on an instance of
"Other".

The C# 3.0 language spec describes it like this in section 3.5.3:
<quote>
When a protected instance member is accessed outside the program text
of the class in which it is declared, and when a protected internal
instance member is accessed outside the program text of the program in
which it is declared, the access must take place within a class
declaration that derives from the class in which it is declared.
Furthermore, the access is required to take place through an instance
of that derived class type or a class type constructed from it. This
restriction prevents one derived class from accessing protected
members of other derived classes, even when the members are inherited
from the same base class.
</quote>

Jon
Jun 27 '08 #3
On Jun 12, 12:55*pm, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
<quote>
When a protected instance member is accessed outside the program text
of the class in which it is declared, and when a protected internal
instance member is accessed outside the program text of the program in
which it is declared, the access must take place within a class
declaration that derives from the class in which it is declared.
Furthermore, the access is required to take place through an instance
of that derived class type or a class type constructed from it. This
restriction prevents one derived class from accessing protected
members of other derived classes, even when the members are inherited
from the same base class.
</quote>
Ok, that makes sense from the example you gave since it's impossible
for the compiler to know whether the passed in object is the base
class from another inheritance branch but you could argue that the
compiler should know this to be impossible in my case since the
creation of the object is within the method and that object is defined
to be derived from the current class that it's in.
Don't get me wrong it's not worth arguing too much because I could
have just kept the original object as a DerivedType type and then
everything would work fine.


Jun 27 '08 #4
Israel <is**********@hotmail.comwrote:
<quote>
When a protected instance member is accessed outside the program text
of the class in which it is declared, and when a protected internal
instance member is accessed outside the program text of the program in
which it is declared, the access must take place within a class
declaration that derives from the class in which it is declared.
Furthermore, the access is required to take place through an instance
of that derived class type or a class type constructed from it. This
restriction prevents one derived class from accessing protected
members of other derived classes, even when the members are inherited
from the same base class.
</quote>

Ok, that makes sense from the example you gave since it's impossible
for the compiler to know whether the passed in object is the base
class from another inheritance branch but you could argue that the
compiler should know this to be impossible in my case since the
creation of the object is within the method and that object is defined
to be derived from the current class that it's in.
You don't want the compiler to start having to make that kind of
inference though - the complexity of the language balloons massively.
Heck, type inference in C# 3 is complicated enough as it is for a
single expression - I don't want to have to wade through rules about
what extra information the compiler is required to take into account.
It would get really hairy.
Don't get me wrong it's not worth arguing too much because I could
have just kept the original object as a DerivedType type and then
everything would work fine.
Exactly. And in cases where you know better than the compiler for
whatever reason, you can always cast. That's what casting's for :)

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jun 27 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Tom Evans | last post by:
My basic question: If I have a specific interface which I know is going to be implemented by a number of classes, but there is no implementation commonality between them, what is the preferred...
4
by: Kevin L | last post by:
Below is a code snippet that fails to compile under vc.net class BaseInterface { public: virtual void f() = 0; }; class BaseImplementation : public BaseInterface {
10
by: Brett | last post by:
I'm still trying to figure out concrete reasons to use one over the other. I understand the abstract class can have implementation in its methods and derived classes can only inherit one abstract...
9
by: Sean Kirkpatrick | last post by:
To my eye, there doesn't seem to be a whole lot of difference between the two of them from a functional point of view. Can someone give me a good explanation of why one vs the other? Sean
4
by: J.M. | last post by:
I have a question concerning inheritance: can an abstract (parent) class have an abstract object? I would like to make a concrete child inherit from this class by inheriting from this object. Let...
7
by: jason | last post by:
In the microsoft starter kit Time Tracker application, the data access layer code consist of three cs files. DataAccessHelper.cs DataAcess.cs SQLDataAccessLayer.cs DataAcccessHelper appears...
0
by: mailforpr | last post by:
Hi. Let me introduce an iterator to you, the so-called "Abstract Iterator" I developed the other day. I actually have no idea if there's another "Abstract Iterator" out there, as I have never...
6
by: Miguel Guedes | last post by:
Hello, I recently read an interview with Bjarne Stroustrup in which he says that pure abstract classes should *not* contain any data. However, I have found that at times situations are when it...
6
by: hsmit.home | last post by:
Hello, I came across a strange error and it's really been bugging me. Maybe someone else has come across this and any insight would be appreciated. What I'm trying to accomplish is using...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.