I have a question regarding inheritance in C#. I have a public abstract class A that defines protected virtual members. I have another abstract class B that inherits from A, and then another internal class C, inheriting from B. The first class A is in a separate namespace, and the other two are in the same namespace, but include a reference to the first.
I was trying to access the protected virtual member of A in C using base keyword, but am unable to unless I provide a method in B and then call A's protected virtual member there.
I want to know if what I was trying to do is possible, i.e. was I doing something incorrectly? Or if its not possible, then why?
Thanks.
Here's the code sample :
namespace A
{
public abstract class BaseClass
{
protected virtual string GetData()
{
//code to get data
}
}
}
namespace B //includes a reference to A
{
abstract class DerivedClassA : BaseClass
{
}
internal class DerivedClassB: DerivedClassA
{
public void write()
{
base.GetData(); // results in error.
// The name 'GetData' does not exist in the current context
// and DerivedClassA does not contain a definition for 'GetData'
}
}
Other than a namespace issue your code ran fine, the one thing I had to change was change DerivedClassA to
abstract class DerivedClassA : A.BaseClass
{
}
What I suspect is whatever BaseClass is called in your real project you have a class of the same name in namespace B or some other namespace you have included in your using statements at the top of your code. For example this would recreate your error
namespace A
{
public abstract class BaseClass
{
protected virtual string GetData()
{
throw new NotImplementedException();
}
}
}
namespace B //includes a reference to A
{
public abstract class BaseClass
{
}
abstract class DerivedClassA : BaseClass
{
}
internal class DerivedClassB: DerivedClassA
{
public void write()
{
base.GetData(); // results in error.
// The name 'GetData' does not exist in the current context
// and DerivedClassA does not contain a definition for 'GetData'
}
}
}
Check that you don't have another namespace that uses the same name as BaseClass or explicitly define the namespace of BaseClass in DerivedClassA
This works for me.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Protectedmemberinabstractclassex
{
class Program
{
static void Main(string[] args)
{
}
}
}
namespace A
{
public abstract class BaseClass
{
protected virtual string GetData()
{
throw new NotImplementedException();
}
}
}
namespace B //includes a reference to A
{
abstract class DerivedClassA : A.BaseClass
{
}
internal class DerivedClassB : DerivedClassA
{
public void write()
{
base.GetData();
}
}
}
Got the source of the problem. Apparently, the location of the dlls that the second namespace was referring to had changed and hence, it was pointing to an outdated reference. After I updated the references from the correct location, it ran fine. Thanks all for the help.
Related
Error 1 'Interface.myDerivedClass.myMethod()': virtual or abstract members cannot be private c:\users\igmfun\documents\visual studio 2012\Projects\Interface\Interface\Program.cs 16
Making a virtual or abstract member private would make it inaccessible to other classes, including derived classes, making it impossible to override the method, making its virtual, or abstract quality meaningless. I get it.
But wait... The compiler is complaining about the member in the derived class, not the base class... And I never declared that member as virtual or abstract... so did the overriding member (the one in the derived class) inherit the virtual or abstract quality from the virtual or abstract member it is overriding?
Also, if I change
override void myMethod(){}
to
public override void myMethod(){}
I get a new error,
"No suitable method found to override."
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Interface
{
interface myInterface
{
void myMethod();
}
class myDerivedClass : myInterface
{
override void myMethod()
{
}
}
class Program
{
static void Main(string[] args)
{
}
}
}
The error is somewhat misleading - it looks like compiler tried first to reason locally about code. So it found you are doing override with private (default) specifier. This is clearly an error, but it actually hides the real one - there is nothing to override to start with (you can see that if you change code to public override void myMethod(){}).
Actual fix is to make method public as it implements an interface method:
class MyInterfaceImplementationClass : IMyInterface
{
public void MyMethod()
{
}
}
Alternatively you can explicitly implement the interface too if you prefer method to be not visible from the class directly (similar to private, but you can call by casting to interface):
class MyExplicitInterfaceImplementationClass : IMyInterface
{
void IMyInterface.MyMethod()
{
}
}
interface IMyInterface
{
void MyMethod();
}
I think you are confusing Interface with Class.
If you want a base class to derive from use the class keyword not interface
public class BaseClass
{
public void MyMethod()
{
}
}
public class DerivedClass : BaseClass
{
}
If you want to be able to override the method in the base class you can mark it as virtual and use the override keyword in the derived class
public class BaseClass
{
public virtual void MyMethod()
{
}
}
public class DerivedClass : BaseClass
{
public override void MyMethod()
{
// do soothing different
base.MyMethod()
}
}
using System.IO;
using System;
using Assembly2;
// DLL 1
namespace Assembly1
{
class class1 : class2
{
static void Main()
{
Console.WriteLine(new class2().sample); //Cannot access. Protected means --> accessible to the derived classes right ? (But, note that this is a different assembly. Does not work because of that ?)
}
}
}
// DLL 2
namespace Assembly2
{
public class class2
{
protected string sample = "Test";
}
}
In the above simple code,
I cannot access the string sample in assembly 2 though I am deriving from class2
From MSDN:
The type or member can be accessed only by code in the same class or struct, or in a class that is derived from that class.
Does this definition stand only for the same assembly or can the protected members be accessed across assemblies ?
You can access the protected member from a different assembly, but only within a subclass (as normal for protected access):
// In DLL 1
public class Class3 : class2
{
public void ShowSample()
{
Console.WriteLine(sample);
}
}
Note that your current code would fail even if the classes were in the same assembly.
A protected member of a base class is accessible in a derived class only if the access occurs through the derived class type.
class class1:class2
{
static void Main()
{
Console.WriteLine(new class1().sample);
}
}
now above code will run.
There is a virtual method in a library that my C# project references. How can I override this method in another class within my application?
Example:
namespace TheLibary
{
class SomeClass
{
public virtual void TheMethod()
{
//Do Stuff
}
}
}
Then in my project:
using theLibary;
namespace TheProject
{
class SomeClass
{
public override <Help>
}
}
Edit: Confusion and totally forgetting that this class didn't inherit from the libraries class messed me up, it was late :)
You should study a bit about OOP (and inheritance in particular) before getting down to any serious coding. For quick reference, here’s an example of how to override a method:
namespace TheDll
{
public class SomeClass
{
public virtual void TheMethod()
{ }
}
}
namespace TheProject
{
public class DerivedClass : SomeClass
{
public override void TheMethod()
{ }
}
}
You should observe that the signature of the overriding method (including its name) must be the same. The derived class, on the other hand, may (and typically should, for clarity) be named differently.
I have two classes, Class A and Class B. These both classes are lying in two different namespaces.
I call a static method of Class B from Class A, then how can I get complete information of Class A and its namespace in called static method of Class B?
I do not want to add any code in class A
But can add anything into class B.
Through Reflection.
http://msdn.microsoft.com/en-us/library/system.reflection.assemblyname.aspx
obj.GetType().FullName;
or
typeof(AClass).FullName;
You should use the GetType() method on your A object.
namespace nmspA {
public class A{
private void DoSomething(){
B.Foo(this);
}
}
}
namespace nmspB {
public class B {
public static void Foo(A a){
Debug.Write(a.GetType()); // Will write : "nmspA.A"
}
}
}
How about you pass class A as a parameter to class B? Like:
public class A{
public void CallB(){
ClassB.MyMethod(this);
}
}
public static class B {
public static void MyMethod(A a){
// get info about class a here.
}
}
Of course, you can also look at the options you have with reflection if you do not want to pass the object as a parameter.
Can I create partial class in different namespaces? Will it work correct?
e.x.:
class1.cs
namespace name1
{
public partial class Foo
{
Bar1(){
return 10;
}
}
}
class2.cs
namespace name1.name2
{
public partial class Foo
{
Bar2(){
return 100;
}
}
}
main.cs
using name1;
using name1.name2;
namespace mainClass
{
public class mainClass
{
Foo classFoo = new Foo();
int Count = classFoo.Bar1() + classFoo.Bar2();
// Will Count = 110?
}
}
What should I do to make it work? (if my example not correct)
A class's name includes it's namespace, so name1.Foo and name1.name2.Foo are two completely separate types. So the short answer to your question is: No.
Why do you need to do something like this?
Partial class is only possible in same namespace and same assembly.
Namespace could be in two different assemblies but partial class could not.
Here are some point to consider while implementing the partial classes:-
Use partial keyword in each part of partial class.
Name of each part of partial class should be the same but source file name for each part of partial class can be different.
All parts of a partial class should be in the same namespace.
Each part of a partial class should be in the same assembly or DLL, in other words you can't create a partial class in source files of a different class library project.
Each part of a partial class has the same accessibility. (like private, public or protected)
If you inherit a class or interface on a partial class then it is inherited on all parts of a partial class.
If a part of a partial class is sealed then the entire class will be sealed.
If a part of partial class is abstract then the entire class will be considered an abstract class.
Partial Classes in C#
This will not work. The compiler will give you an ambiguous name error on the Foo classFoo = new Foo(); line. For partial classes to work, they must be in the same namespace because the namespace is actually part of the fully qualified name of the type.
Also, for static classes you can implement something like this with the help of fresh C# 6.0 using static feature.
Consider:
namespace SomeLogic1
{
public static class Util
{
public static int Bar1()
{
return 1;
}
}
}
namespace SomeLogic2
{
public static class Util
{
public static int Bar2()
{
return 2;
}
}
}
namespace GeneralStuff
{
using SomeLogic1;
using SomeLogic2;
public class MainClass
{
public MainClass()
{
// Error CS0104
// 'Util' is an ambiguous reference between 'SomeLogic1.Util' and 'SomeLogic2.Util'
var result = Util.Bar1() + Util.Bar2();
}
}
}
Right, that does not compile, the error message is clear. To fix the situation you can directly specify namespaces (but you don't want this as far as I understand):
namespace GeneralStuff
{
public class MainClass
{
public MainClass()
{
var result = SomeLogic1.Util.Bar1() + SomeLogic2.Util.Bar2();
}
}
}
OR you can apply using static feature this way:
namespace GeneralStuff
{
using static SomeLogic1.Util;
using static SomeLogic2.Util;
public class MainClass
{
public MainClass()
{
var result = Bar1() + Bar2();
}
}
}
Perhaps it is ok to do this for some helper/utils classes. But partial classes are not the way, as other have noticed.
Restrictions on partial classes and method from MSDN https://msdn.microsoft.com/en-us/library/wa80x488.aspx
I am assuming your main goal was to distribute the methods amongst different namespaces, otherwise it would have been trivial (put everything in one class whether partial or not and you're done).
So the assumed objectives are:
Have the 2 methods Bar1 in namespace name1 and Bar2 in namespace name1.name2
Be able to invoke any of the above methods in the context of one class, here ClsFoo
You can't achieve this with partial classes, but you can achieve it in a different way: if you use extension methods and bind them to a particular class, here ClsFoo, then you can do the following:
using SomeOtherNamespace;
using name1;
using name1.name2;
namespace mainClass
{
public static class mainClass
{
public static void Main()
{
var classFoo = new ClsFoo();
var count = classFoo.Bar1() + classFoo.Bar2();
Console.WriteLine($"count = {count}"); // output is 110
} // main
} // class
} // namespace
namespace SomeOtherNamespace
{
public class ClsFoo
{
// does not need to contain any code
} // class
} // namespace
namespace name1
{
public static class FooExt
{
public static int Bar1(this ClsFoo foo)
{
return 10;
} // method
} // class
} // namespace
namespace name1.name2
{
public static class FooExt
{
public static int Bar2(this ClsFoo foo)
{
return 100;
} // method
} // class
} // namespace
Run it online
This way, you declare an empty class ClsFoo and then write some extension methods Bar1() and Bar2(), which reside in different namespaces and static extension classes.
Note: The extension classes may have the same name FooExt as long as they are in different namespaces, of course you can also give them different names like FooExt1 and FooExt2 if you like - and the example will still work; even in older versions of C#.