I have a structure with several namespaces, and in each namespace I have one static class that is sort of a small, little spider in the net of that namespace. Like the head of the department.
Let's take an example of two namespaces, Foo.Bar.Baz and Foo.Bar.Quux.
I have one file which looks like this:
namespace Foo.Bar.Baz
{
static class Baz
{
public static void DoSomething()
{
Console.Writeline("Doing something...");
}
}
}
And then a second file:
using Foo.Bar.Baz
namespace Foo.Bar.Quux
{
static class Quux
{
public static void GetToWork()
{
Baz.DoSomething();
}
}
}
Now, I get an error in the second file when I try to compile because it thinks that Baz is the namespace and not the class. But since I have the line using Foo.Bar.Baz it should be fine to use any class inside that namespace without needing to prefix it with the name of the namespace, right? I can use other stuff from that namespace correctly, but not a class with the same name.
It kinda feels like the compiler secretly adds this line to every file: using Foo.Bar.
Also, I cannot just put the static Baz class inside the Foo.Bar namespace since then I will get errors saying that Foo.Bar.Baz is not a namespace (since I have other stuff in that namespace and have files that use that namespace). Then it seems the compiler sees the static class and decides that Foo.Bar.Baz is a static class and not a namespace.
Of course, I could just rename the static classes to something like Manager but then I would still have to spell out the full Baz.Manager.SomeMethod and Quux.Manager.SomeMethod in files that need to access stuff from both namespaces. This feels rather clumpsy, I'd rather just have it be Baz.SomeMethod and Quuz.SomeMethod.
Any ideas?
Maybe this can help:
using Baz = Foo.Bar.Baz.Baz;
Since Baz is a static class, it cannot contain instance members. So, DoSomething() must be declared as a static method.
Once you have this, you can either do this:
using Foo.Bar.Baz;
public void GetToWork()
{
Baz.Baz.DoSomething();
}
or this:
using baz = Foo.Bar.Baz.Baz;
public void GetToWork()
{
baz.DoSomething();
}
However, I do agree with the comments in your question that using the same name for the namespace (logical container for a set of classes) and its containing class (encapsulates data and behavior) may result in readability / maintainability issues.
Related
My understanding is that it is similar to write code directly into the old "static void Main(string[] args)" without the need to display what's above.
However, I used to declare my variables in the class Program to have them accessible from other classes (apologies if not best practice, I learnt C# by myself and as long as it works, I'm happy with my code).
See example below:
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
namespace myNameSpace
{
class Program
{
//variables declaration
public static string abc = "abc";
public static int xyz = 1;
static void Main(string[] args)
{
//code goes here
}
}
}
With C# 9, it seems I can only declare variables in the Main section, so how can I declare them to be able to access them from other classes?
I don't think the currently-accepted answer is correct, if you toss a partial class signature in Program.cs you can most certainly add things like static-scoped fields and attributes:
var customAttributes = (CustomAttribute[])typeof(Program).GetCustomAttributes(typeof(CustomAttribute), true);
Console.WriteLine(customAttributes[0].SomePropery);
Console.WriteLine(MyField);
[Custom(SomePropery = "hello world")]
public partial class Program
{
private const string MyField = "value";
}
class CustomAttribute : Attribute
{
public string SomePropery { get; set; }
}
The above code and nothing else in Program.cs will output:
/home/dongus/bazinga/bin/Debug/net6.0/bazinga
hello world
value
Process finished with exit code 0.
I use this method to apply the [ExcludeFromCodeCoverage] attribute to my projects' Program.cs files
For .Net 5:
When you use the Top-Level Program feature of C# 9, you give up the ability to put anything outside the Main method scope. Fields, properties, attributes on the Main method or Program class, setting the namespace, changing the class name, etc are all no longer available (the only exception is "importing" namespaces with using lines).
If that limitation doesn't work for you, don't use the feature.
For .Net 6 and higher, use dongus's answer.
In C#, if I create a class with no namespace, what namespace will I use when trying to instantiate the class?
For example, assume main is...
namespace NamespaceTests
{
class Program
{
static void Main(string[] args)
{
}
}
}
... and assume my namespace-less class is ...
public class test
{
public string SayHello()
{
return "Hello World!";
}
}
... and assume I have another class by the same name, but having the default namespace...
namespace NamespaceTests
{
public class test
{
public string SayHello()
{
return "Hello Moon...";
}
}
}
... how would I modify main to include an instance of the namespace-less class and call 'SayHello' to retrieve the message "Hello World!"? Specifically, how would I fully qualify the namespace-less instance of class 'test', especially considering I may have another class also called 'test' but having a namespace, so I need to distinguish...
It's in the global namespace and can be referenced like this:
var x = new global::test();
Types not defined within a namespace will be in the global namespace.
The global contextual keyword, when it comes before the :: operator, refers to the global namespace, which is the default namespace for any C# program and is otherwise unnamed.
The following example shows how to use the global contextual keyword
to specify that the class TestApp is defined in the global namespace:
C# class TestClass : global::TestApp { }
In the addition to above answers, it is important to note, what all Type, regardless of its declaration location, has a "fully qualified name", which begins from "global::"
From "O'Relly. C# in a Nutshell":
All type names are converted to fully qualified names at compile time. Intermediate Language (IL) code contains no unqualified or partially qualified names
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.
Why I'm unable to extend an abstract class. Is there any work around to achieve this?
In silverlight, Enum.GetNames is missing. So, I would like to extend it and have it in my utility assembly. By then, got into this.
The problem here is not that you can't add an extension method to an abstract class (you can - you can add an extension method to any type) - it's that you can't add a static method to a type with extension methods.
Extension methods are static methods that present themselves in C# as instance methods. But they're still static. Adding a static method to a type requires the ability to redefine the type, which you can only do if you have the source code :)
Best bet, if you want this method, is to write your own static and see if you can perhaps rip the code out of reflector.
However, it's entirely possible that it's not there because it's physically not supported in Silverlight (I don't know - I haven't investigate)
EDIT
Following on from your comment - and I hope that I've understood you here - I think what you want to be able to do is something like this (targetting object to prove the point):
public static class ExtraObjectStatics
{
public static void NewStaticMethod()
{
}
}
public class Test
{
public void foo()
{
//You can't do this - the static method doesn't reside in the type 'object'
object.NewStaticMethod();
//You can, of course, do this
ExtraObjectStatics.NewStaticMethod();
}
}
If you think about it - of course you can't inject new static methods into an existing type because, like I said in paragraph two, you have to be able to recompile the underlying type; and there simply is no way around that.
What you can do is (and I don't actually recommend this - but it's an option) create yourself a new type called Enum and place it inside a new namespace:
namespace MySystem
{
public class Enum
{
public static string[] GetNames()
{
//don't actually know how you're going to implement it :)
}
}
}
And now - when you want to use it, what you can't do is this:
using System;
using MySystem;
namespace MyCode
{
public class TestClass
{
public static void Test()
{
Enum.GetNames(); //error: ambiguous between System and MySystem
}
}
}
Because the using in the outermost scope to both 'System' and 'MySystem' will cause the compiler not to be able to resolve the correct Enum type.
What you can do, however, is this:
using System;
namespace MyCode
{
using MySystem; //move using to inside the namespace
public class TestClass
{
public static void Test()
{
//will now work, and will target the 'MySystem.Enum.GetNames()'
//method.
Enum.GetNames();
}
}
}
Now, code within that namespace (within that file only) will always resolve Enum to the one in your namespace because that's the nearest using directive in terms of scope.
So, you can think of this as overriding the whole Enum type for the benefit of a given namespace that includes a using MySystem; in it.
But, it does exactly that - it replaces the existing System.Enum with MySystem.Enum - meaning that you lose all the members of the System.Enum type.
You could get around this by writing wrapper methods in your Enum type around the System.Enum versions - making sure that you fully-qualify the type as System.Enum.
Having looked at the implementation of the GetNames method in Reflector - it relies on internal data that I don't think you're going to be able to build... but I would be very interested to hear if you are actually able to reproduce the method in Silverlight.
public abstract class Foo
{
public abstract void Bar();
}
public static class FooExtensions
{
// most useless extension method evar
public static void CallBar(this Foo me)
{
me.Bar();
}
}
Sure, no problem.
How is it possible that .NET is finding the wrong 'MyType' in this scenario?
I have a type A.B.C.D.MyType in a project that I'm working on, and I'm referencing a DLL that has a type A.B.MyType? I do not have any 'using A.B;' statements anywhere in my code, and I do have 'using A.B.C.D;'. When I compile, the compiler thinks any naked reference to 'MyType' means 'A.B.MyType'.
I know I could just rename the class or use an alias, but I'm wondering how this is even possible.
Any ideas?
Thanks!
Are you working in a namespace that is under A.B namespace? (for example A.B.X) if so the C# namespace resolutions (ECMA-334 C# Language Specification : 10.8 10.8 Namespace and type names) says:
... for each namespace N, starting
with the namespace in which the
namespace-or-typename occurs,
continuing with each enclosing
namespace (if any), and ending with
the global namespace, the following
steps are evaluated until an entity is
located...
and then followed by:
If K is zero and the namespace
declaration contains an
extern-alias-directive or
using-aliasdirective that associates
the name I with an imported namespace
or type, then the
namespace-or-type-name refers to that
namespace or type
This means that name resolution starts at the current namespace and searches all namespaces up to the root, and only after this hierarchical search ends, then the namespaces imported with the using clause are searched.
The following example prints "Ns1.Foo"
using Ns1.Foo.Foo2;
namespace Ns1.Foo
{
class Foo
{
public void Print()
{
System.Console.WriteLine("Ns1.Foo");
}
}
}
namespace Ns1.Foo.Foo2
{
class Foo
{
public void Print()
{
System.Console.WriteLine("Ns1.Foo.Foo2");
}
}
}
namespace Ns1.Foo.Bar
{
class Bar
{
public void Print()
{
new Foo().Print();
}
static void Main()
{
new Bar().Print();
}
}
}
Edit: Adding a using clause inside a namespace, will make so that the namespace is searched before the hierarchical search of current namespace is done is done. Change the example to:
namespace Ns1.Foo.Bar
{
using Ns1.Foo.Foo2;
class Bar
{
public void Print()
{
new Foo().Print();
}
static void Main()
{
new Bar().Print();
}
}
}
and Ns1.Foo.Foo2 will be printed.
Edit: changed example
Is your code in namespace A.B or A.B.C? If so, that's probably the issue. Use a using directive like this:
using TheTypeIWant = A.B.C.D.MyType;
then just refer to TheTypeIWant in your code.
EDIT: I've just tried the "using MyType=A.B.C.D.MyType" option, but that doesn't work. The above is fine though.
Just a guess: in your project properties, is the "default namespace" set to A.B ?