Does inheritance also automatically "inherit" namespaces from its parent? - c#

Just wanted to ask generic question about Namespaces. If class A inherits class B and doesn't explicitly reference (using) B's namespace, do I have to explicitly using B namespace in my calling code to call B's methods from an instance of A? Is this language dependent (C#, C++)?
Ex in C#:
// Namespace X
class A : B
{
public void methodA(){...}
}
// Namespace Y
class B
{
public void methodB(){...}
}
In other code using A:
using X;
// do I need using Y?
...
A obj = new A();
obj.methodB(); // calls methodB() using instance of A
...

if A is in namespace X and B in Y, you can't do
// Namespace X
class A : B
{
...
};
you need to do:
class A : Y::B
{
...
};
So you see you had to inherit B using the qualification and there's nothing special going on there. This is in C++ btw.
If A needs anything more from Y it'll need to similarly qualify it.
Anybody using A needs to qualify it with X::A or import everything or just A, depending, to use it - using X::A; or using namespace X;. That has no effect on what happens to the visibility of things inside Y though.
The only thing that might surprise you is Koenig Lookup, so maybe read that.

No namespaces are not inherited by classes in C++ (and in C#). However due to the ADL (Argument Dependent Lookup) you can "inherit" some names from the namespace of a base class.
Here is a demonstrative program
#include <iostream>
namespace N1
{
struct A {};
void f( const A & )
{
std::cout << "N1::f( const A & )\n" << '\n';
}
}
namespace N2
{
struct B : N1::A
{
B() { f( *this ); }
};
}
int main()
{
N2::B b;
return 0;
}
Its output is
N1::f( const A & )
To "inherit" a namespace you can use the using directive in a namespace or in a block scope. For example
namespace N1
{
struct A {};
}
namespace N2
{
using namespace N1;
struct B : A
{
};
}
Take into account that you may not use the using directive in a class scope.
Or you can introduce only some names by means of a using declaration.

Classes do not inherit namespaces. using only imports the symbols in a namespace into the current source file. It has no effect on your classes themselves.
This C# code:
using System;
public class A {
public void Run() {
Console.WriteLine("Foobar");
}
}
Is completely equivalent in its effects, both in the CIL emitted as well as how users of A will use the class or derive it, to this code:
public class A {
public void Run() {
System.Console.WriteLine("Foobar");
}
}
Let's say that we import a type that we return from a method:
using System.IO;
public class A {
public Stream createStream() {
// implementation irrelevant
}
}
If we then declare class B : A in another source file, the createStream() method is inherited, and it still returns System.IO.Stream, even if the source file B is declared in doesn't have using System.IO, and users of class B do not need to import System.IO in order to use the stream returned by createStream(); the system knows the fully-qualified type is System.IO.Stream.
public class B : A {
public void doSomethingWithStream() {
// We can use a System.IO.Stream object without importing System.IO
using (var s = createStream()) {
}
}
}
public class C {
public static void doSomethingElseWithStream(B b) {
// As can other stuff that uses B.
using (var s = b.createStream()) {
}
}
}

No, there is no such thing as a inherited namespace.
Namespace does not have anything that can be derived/inherited.
If you want to inherit a class A that is in different namespace, you need to add "using namespace ..."

Related

mono_class_from_name_case returns nullptr

mono_class_from_name_case returns nullptr and i found no way to get more information why, and the mono documentation is very basic. My question is, i think i am missing something, is there a method to "link" the two assemblys together?, is that even needed?, why is the class showing up in the metadata but not accessable via get class?
I get the name and namespace through the metadata interface and they are valid strings. The dlls are compiled without any warnings/errors.
Beetween the open of the assambly and the metadata access is no other operation.
The code is first executed for base.dll then for content.dll. Both are in the same Domain, but different Assemblys and images.
Things i noticed:
Removing the base class in Slime "fixes" it. <- maybe missing a reference to base.dll?
It still does not work, when making the base not abstract/without any virtual method
Changing from mono_class_from_name_case to mono_class_from_name has the same behavior.
C++ Code:
//metadata.getRaw returns a MonoImage* loaded with mono_domain_assembly_open & mono_assembly_get_image, the base dll is loaded first
const MonoTableInfo* table_info = mono_image_get_table_info(metadata.GetRaw(), MONO_TABLE_TYPEDEF);
int rows = mono_table_info_get_rows(table_info);
for (int i = 0; i < rows; i++)
{
MonoClass* _class = nullptr;
uint32_t cols[MONO_TYPEDEF_SIZE];
mono_metadata_decode_row(table_info, i, cols, MONO_TYPEDEF_SIZE);
const char* name = mono_metadata_string_heap(metadata.GetRaw(), cols[MONO_TYPEDEF_NAME]);
const char* name_space = mono_metadata_string_heap(metadata.GetRaw(), cols[MONO_TYPEDEF_NAMESPACE]);
//this returns nullptr for a valid class, i think the base dll is not loaded
_class = mono_class_from_name_case(metadata.GetRaw(), name_space, name);
//this does happen...
if (_class == nullptr) {
continue;
}
}
The two involved DLLs:
Base.dll
csc.exe -target:library -nologo -optimize+ -debug- -out:Base.dll Item.cs
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Base
{
public abstract class Item
{
public Item()
{
}
public abstract bool init();
public abstract void release();
}
}
Content.dll
csc.exe -target:library -nologo -optimize+ -debug- -reference:Base.dll -out:Content.dll Slime.cs
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Content{
public class Slime : Base.Item
{
public Slime()
{
}
public override bool init()
{
return true;
}
public override void release()
{
}
}
}
I found the "error" there is a difference beetween mono_assembly_load and mono_domain_assembly_open. With mono_assembly_load it works.

Expected class, delegate, enum, interface, or struct (CS1518)

simple code here and the answers I find don't seem to work.
I'm using
SharpDevelop Version : 3.2.1.6466
.NET Version : 2.0.50727.5485
The problem is the error code
Expected class, delegate, enum, interface, or struct (CS1518).
Any ideas?
Program.cs codes:
using System;
using System.Threading;
namespace Threshold
{
public class Class1
{
public Class1()
{
Heritage YOLO = new Heritage();
YOLO.Fractal();
}
}
static void Main()
{
//do nothing
}
}
The cs file it calls is:
using System;
using System.Threading;
namespace Threshold
{
public class Heritage
{
int Fractal()
{
//Do stuff.
}
}
internal partial class DefineConstants
{
public const string DRIVERPATH = "d:\\tc\\bgi";
}
}
Please help with a fix.
Thanks.
Your main method is outside the class. Put it inside.

Why do I need fully qualified name to access static property of a class that was included with "using"

If I have this class declaration
namespace DatabaseCache
{
public class DatabaseCache
{
public static bool somePublicFlag ;
}
}
In another class I have this statement
using DatabaseCache;
Why do i need to write a statement like this in that class
DatabaseCache.DatabaseCache.somePublicFlag = true ;
instead of just
DatabaseCache.somePublicFlag = true ;
You don't need that if you don't have a Namespace and Type name collision. A well designed library will not have such collision, So design your library accordingly to avoid such collision.
namespace DatabaseCache
{
//change the name of the class
public class DifferentNameThanNamespace
{
public static bool somePublicFlag ;
}
}
Because the compiler doesn't know if DatabaseCache is referring to the namespace or the class. Even thought you're using the namespace it's still perfectly legal to preface types within that namespace by the namespace, so the call is ambiguous.
You could alias the type by using:
using DC = DatabaseCache.DatabaseCache;
and then just calling
DC.somePublicFlag
but that's just masking the problem - renaming the namespace is a better solution.
In order to avoid ambiguities, it is not recommanded to declare a class with the same same as its namespace.
The Framework Design Guidelines say in section 3.4 “do not use the same name for a namespace.
To learn about how to activate/disable this kind of warning see this link
(Of course the advice is to not use the same name for two distinct things.)
Answer with an extension. Suppose you have one file with:
namespace DatabaseCache
{
public class DatabaseCache // same name as namespace :-(
{
public static bool somePublicFlag;
}
public class somePublicFlag // evil other type
{
}
}
Then now it depends on where you put your using directives relative to your namespace. For example, in another file, this will be legal:
namespace Other
{
using DatabaseCache;
class DbcTestClass1
{
void M()
{
DatabaseCache.somePublicFlag = true; // legal!
}
}
}
In the above example, somePublicFlag refers to the field of the class!
However, this is legal as well:
using DatabaseCache;
namespace Other
{
class DbcTestClass2
{
void M()
{
var instance = new DatabaseCache.somePublicFlag(); // legal!
}
}
}
With that placing of the using directive, the somePublicFlag refers to the "evil" class of that name. The qualifier DatabaseCache. in this case is redundant, but it is still seen as a reference to the namespace global::DatabaseCache because the global namespace (null namespace) is searched first in this case.
To learn more, see my answer elsewhere. It all depends on the order in which the different namespaces (including the global namespace) are searched for a matching name.

Namespace access issue with sub namespaces

I have two classes in the different sub namespaces:
namespace Acme.ByteTools
{
class ByteTools
{
...
}
}
namespace Acme.IO
{
class Reader
{
...
}
}
While I trying to access Acme.ByteTools from the any third namespace, I use:
using Acme.ByteTools;
...
ByteTools.BytesToUint(...);
but when I try to access Acme.ByteTools from Acme.IO, compiler require different notation:
using Acme.ByteTools;
...
ByteTools.ByteTools.BytesToUint(...);
Why?
As others including the legendary Eric Lippert have stated...please don't create collisions. I've seen code riddled with using alias directives because of collisions and I simply cannot express how frustrating it is to see a namespace change its name from class to class.
The confusion speaks for itself. Just look at something like this:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
A a = new A();//A's a namespace
A.A b = new A.A();//A is a namespace this works!
global::A.A nuts = new A();//This fails...ugh
Console.ReadLine();
}
}
}
namespace A
{
class A
{
public void DoWork()
{
A a = new A();//A's a class
A.A b = new A.A();//A is a type (class) A.A makes no sense to the compiler
global::A.A nuts = new A();//Oh but this works fine
}
}
}
So the fix is make sure the namespaces and classes are different. A using alias directive using B = A; might ease the pain however that directive can change from file to file and anything to its right must be fully qualified.

Why do extension methods not work with namespace aliasing?

This may be an ignorant question, but I'm unsure why I can not use namespace aliasing and extension methods together.
The following example works just fine:
Program.cs
using System;
using ExtensionMethodTest.Domain;
namespace ExtensionMethodTest
{
class Program
{
static void Main(string[] args)
{
var m = new Domain.MyClass();
var result = m.UpperCaseName();
}
}
}
MyClass.cs
using System;
namespace ExtensionMethodTest.Domain
{
public class MyClass
{
public string Name { get; set; }
}
}
MyClassExtensions.cs
using System;
namespace ExtensionMethodTest.Domain
{
public static class MyClassExtensions
{
public static string UpperCaseName (this MyClass myClass)
{
return myClass.Name.ToUpper();
}
}
}
However, when I alias domain as follows in Program.cs:
using Domain = ExtensionMethodTest.Domain;
The extension method no longer works..
This can be rather frustrating when I'm dealing with converting various domain objects to contract objects (let's say I have 4 domain assemblies and 4 contract assemblies) for use in a web service. Using aliasing would be very handy as I could alias as follows and continue to use the various extension methods (such as ToContract, etc.):
using BillingContracts = Namespace.Billing.Contracts;
using IssuingContracts = Namespace.Issuing.Contracts;
etc...
I look forward to the answer.. I'm sure it's straight forward, but I, for the life of me, can't figure out why it doesn't work.
Thanks!
Make sure to still add a non-aliased using statement:
Program.cs
using System;
using ExtensionMethodTest.Domain; //DON'T FORGET A NON-ALIASED USING
using MyDomain = ExtensionMethodTest.Domain;
namespace ExtensionMethodTest
{
class Program
{
static void Main(string[] args)
{
var m = new MyDomain.MyClass();
var result = m.UpperCaseName();
}
}
}
MyClass.cs
using System;
namespace ExtensionMethodTest.Domain
{
public class MyClass
{
public string Name { get; set; }
}
}
MyClassExtensions.cs
using System;
namespace ExtensionMethodTest.Domain
{
public static class MyClassExtensions
{
public static string UpperCaseName (this MyClass myClass)
{
return myClass.Name.ToUpper();
}
}
}
I also love to use namespace aliasing but its not working in case of Extension methods. So one thing that i did is, I changed the namespace of extension class to same namespace that my main project has (although my extension class resides in sub folder of main project).
Suppose I have a project myFirstProj which surely has namespace myFirstProj for root classes. My extension class is present in myFirstProj/Common/myExtensionClass with contains namespace myFirstProj.Common { //myExtensionClass }.
So now what I did is, I changed the namespace of myExtensionClass from namespace myFirstProj.Common{ //myExtensionClass } to namespace myFirstProj{ //myExtensionClass } .
Now i can use my extension methods in my whole project myFirstProj event without specifying using statement for my extension class.
I know this isn't a standard way to that but I haven't found any other workaround for it expect this one because for my Project there is a requirement to go with namespace aliasing for project namespaces.

Categories