Namespace vs Class Declaration - c#

I'm new to C# and I can't seem to find any info on this so I will ask it here.
Do classes in namespaces have to ever be declared?
using System;
public class myprogram
{
void main()
{
// The console class does not have to be declared?
Console.WriteLine("Hello World");
}
}
If I'm not using a namespace then I have to declare a class
class mathstuff
{
private int numberone = 2;
private int numbertwo = 3;
public int addhere()
{
return numberone + numbertwo;
}
using System;
public class myprogram
{
void main()
{
// the class here needs to be declared.
mathstuff mymath = new mathstuff();
Console.WriteLine(mymath.addhere());
}
}
Am I understanding this correctly?

A namespace is simply a way to make clear in which context the class is living in. Think of your own name, Ralph. We have many Ralphs in this world, but one of that is you. An extra way to get rid of the ambiguity is to add your surname. So that if we have 2 Ralphs, we have a bigger chance of talking about you.
The same works for classes. If you define class AClass and you would have the need of define another class AClass there would be no way to distinguish between the two. A namespace would be that 'surname'. A way of having to classes, but still able to distinguish between the two different classes, with the same name.
To answer your question, it has nothing to do with "not having to declare". It would only be easier to write code.
For example:
using System;
public class myprogram
{
void main()
{
// the class here needs to be declared.
Console.WriteLine("blah");
}
}
Because of the using System; you don't have to declare the namespace of Console. There is only one Console available, which lives in the System namespace. If you wouldn't declare your using System; namespace then you'd need to explain where Console can be found. Like this.
System.Console.WriteLine("blah");
From MSDN:
The namespace keyword is used to declare a scope. This namespace scope lets you organize code and gives you a way to create globally unique types.
For more info check MSDN for namespace.

I think what you mean is "can you declare a class without a namespace?". Yes you can, it's referred to as the global namespace.
class BaseClass
{
}
class SubClass : global::BaseClass
{
}
However, this is very bad practice, and you should never do this in a production application.

Related

How to define data types directly in a namespace

What I'm trying to find out whether you can have something like underneath or not:
namespace myNamespace
{
public string myString;
}
I couldn't find anything that explained this, probably because of my terrible searching keywords. Could anyone tell me if there is a way to do this or not?
If this is possible, I may have goofed up something. Either way, I'd like to know.
I wanted to know how to do this because I want to have access to this in the whole namespace without having to go something.myString when I'm inside a different class. This was something that seemed logical in my eyes, but it's apparently not possible.
You can't declare field directly in the namespace:
// doesn't compile
namespace myNamespace
{
public string myString; // <- syntax error
}
but you can emulate such a syntax with a help of using static (C# 6.0+):
namespace MyLibrary
{
// put myString within a static class
public static class MyStorage
{
// let turn field into property
public static string myString {get; set;}
}
}
Then use the static class with using static:
// please, notice "using static"
using static MyLibrary.MyStorage;
namespace myNamespace
{
public class MyClass
{
public void MyMethod()
{
myString = "abc"; // as if it has been declared in the namespace
string test = myString;
...
}
}
}

Is it possible to do relative C# namespace reference?

I have namespaces:
MyProject.Core.Db
MyProject.Core.Model
And I have classes:
MyProject.Core.Db.User
MyProject.Core.Model.User
Is it possible something like:
using MyProject.Core;
namespace MyProject.BLL
{
public class Logic
{
public static void DoSomething()
{
var userEntity = new Db.User();
var userModel = new Model.User();
}
}
}
I just want to avoid using suffixes in class names (UserModel, UserEntity).
Is it possible to do in somehow in C#?
I don't understand why people say it's not possible. Surely it is possible, you just need to be a bit more specific in the namespaces when you create the target classes (ie you can omit only the common part of the namespace):
namespace MyProject.Core.Db
{
public class User
{
}
}
namespace MyProject.Core.Model
{
public class User
{
}
}
namespace MyProject.BLL
{
public class Logic
{
public static void DoSomething()
{
var foo = new Core.Db.User();
var boo = new Core.Model.User();
}
}
}
The way you're avoiding a fully qualified name within BLL is by being inside of a common namespace with the other two.
What you're trying to achieve is not possible. The closest thing you will get is a using alias directive which looks like this:
using User = Myproject.Core.Db.User;
This will remove the need to fully qualify the path for Myproject.Core.Db.User. You will still need to specify the fully qualified path for at least one of the classes, though. You could create another alias for the other type as Servy demonstrated but at this point I would just rename the classes.
I think the real solution here is to give your classes more descriptive identifiers.
C# does support relative namespace references.
In your case, that means if you're in the namespace MyProject.Core, you can references your classes as Db.User and Model.User. But if you're in the namespace MyProject.BLL, you have to include the Core prefix (Core.Db.User and Core.Model.User).
If that's not good enough for your and you don't want to change your namespace structure, your best choice is probably to add usings to all files that use the types in question.
using DbUser = MyProject.Core.Db.User;
using ModelUser = MyProject.Core.Model.User;
One thing you can do, and we probably should do a lot more, is to specify usings relative to the current namespace. To do this, just move your usings inside the namespace declaration. It doesn't fix your stated problem, but the shorter relative paths are less brittle and your project will be easier to refactor.
namespace MyProject.Core{
using Db;
using Model;
You can add an alias for the one class that you don't import the namespace of:
using MyProject.Core.Db;
using ModelUser = MyProject.Core.Model.User;
namespace MyProject.BLL
{
public class Logic
{
public static void DoSomething()
{
var userEntity = new User();
var userModel = new ModelUser();
}
}
}
In C# it's not possible to use the example that's shown; it's simply not a supported feature.

C# subclass while maintaining name. Deep voodoo?

I have a dll that I'm working with, it contains a class foo.Launch. I want to create another dll that subclasses Launch. The problem is that the class name must be identical. This is used as a plugin into another piece of software and the foo.Launch class is what it looks foe to launch the plugin.
I've tried:
namespace foo
{
public class Launch : global::foo.Launch
{
}
}
and
using otherfoo = foo;
namespace foo
{
public class Launch : otherfoo.Launch
{
}
}
I've also tried specifying an alias in the reference properties and using that alias in my code instead of global, that also didn't work.
Neither of those methods work. Is there a way I can specify the name of the dll to look in within the using statement?
You'll need to alias the original assembly and use an extern alias to reference the original assembly within the new one. Here's an example of the use of the alias.
extern alias LauncherOriginal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace foo
{
public class Launcher : LauncherOriginal.foo.Launcher
{
...
}
}
Here's a walkthrough that explains how to implement that.
Also, you'd mentioned that you tried to use an alias before and encountered problems but you didn't say what they were, so if this won't work then please mention what went wrong.
as Chris said, you can use an alias on your original assembly.
If you can't you that, then you might be able to cheat by using a 3rd assembly
Assembly1.dll (your original)
namespace foo {
public class Launch {}
}
Assembly2.dll (dummy)
namespace othernamespace {
public abstract class Dummy: foo.Launch {}
}
Assembly3.dll (your plugin)
namespace foo{
public class Launch: othernamespace.Dummy{}
}
I'm not even proud of this!
Class name can be identical if it's defined in another namespace, but it boggles the mind why anybody would want to do that to themselves.
Maybe you need to use extern aliases.
For example:
//in file foolaunch.cs
using System;
namespace Foo
{
public class Launch
{
protected void Method1()
{
Console.WriteLine("Hello from Foo.Launch.Method1");
}
}
}
// csc /target:library /out:FooLaunch.dll foolaunch.cs
//now subclassing foo.Launch
//in file subfoolaunch.cs
namespace Foo
{
extern alias F1;
public class Launch : F1.Foo.Launch
{
public void Method3()
{
Method1();
}
}
}
// csc /target:library /r:F1=foolaunch.dll /out:SubFooLaunch.dll subfoolaunch.cs
// using
// in file program.cs
namespace ConsoleApplication
{
extern alias F2;
class Program
{
static void Main(string[] args)
{
var launch = new F2.Foo.Launch();
launch.Method3();
}
}
}
// csc /r:FooLaunch.dll /r:F2=SubFooLaunch.dll program.cs

what does the global:: stand for in C#

What does the global:: stand for in C#? for example what is the difference between
private global::System.Int32 myInt;
and
private int myInt;
Thanks
It's the "global" namespace - it forces the compiler to look for a name without taking other using directives into consideration. For example, suppose you had:
public class Bar{}
namespace Foo
{
public class Bar {}
public class Test
{
static void Main()
{
Bar bar1 = null; // Refers to Foo.Bar
global::Bar bar2 = null; // Refers to the "top level" Bar
}
}
}
Basically it's a way of avoiding naming collisions - you're most likely to see it in tool-generated code, where the tool doesn't necessarily know all the other types in the system. It's rarer to need it in manually-written code.
See "How to: Use the global namespace alias" on MSDN for more details, along with the :: namespace qualifier.
It is the global namespace alias.
If you declare a type called System.Int32 in your codebase, you can distinguish the built in .NET one using this alias.
// your code
namespace System
{
public class Int32
{
}
}
// You could reference the BCL System.Int32 like this:
global::System.Int32 bclInt;
System.Int32 myInt;
See How to: Use the Global Namespace Alias (C# Programming Guide) on MSDN.
It is used to refer to the global namespace. This is useful if you're writing code in a namespace that already exists elsewhere.
See this for more info: http://msdn.microsoft.com/en-us/library/c3ay4x3d.aspx

Namespace-only class visibility in C#/.NET?

In C#, can you make a class visible only within its own namespace without living in a different assembly? This seems useful for typical helper classes that shouldn't be used elsewhere.
(i.e. what Java calls package-private classes)
You can make the classes internal but this only prevents anyone outside of the assembly from using the class. But you still have to make a separate assembly for each namespace that you want to do this with. I'm assuming that is why you wouldn't want to do it.
Getting the C# Compiler to Enforce Namespace Visibility
There is an article here (Namespace visibility in C#) that shows a method of using partial classes as a form of "fake namespace" that you might find helpful.
The author points out that this doesn't work perfectly and he discusses the shortcomings. The main problem is that C# designers designed C# not to work this way. This deviates heavily from expected coding practices in C#/.NET, which is one of the .NET Frameworks greatest advantages.
It's a neat trickā€¦ now don't do it.
I don't think that what you want is possible.
internal is assembly (strictly speaking module) privacy. It has no effect on namespace visibility.
The only way to achieve privacy of a class from other classes within the same assembly is for a class to be an inner class.
At this point if the class is private it is invisible to anything not in that class or the outer class itself.
If protected it is visible to everyone that could see it when private but is also visible to sub classes of the outer class.
public class Outer
{
private class Hidden { public Hidden() {} }
protected class Shady { public Shady() {} }
public class Promiscuous { public Promiscuous() {} }
}
public class Sub : Outer
{
public Sub():base()
{
var h = new Hidden(); // illegal, will not compile
var s = new Shady(); // legal
var p = new Promiscuous(); // legal
}
}
public class Outsider
{
public Outsider()
{
var h = new Outer.Hidden(); // illegal, will not compile
var s = new Outer.Shady() // illegal, will not compile
var p = new Outer.Promiscuous(); // legal
}
}
In essence the only way to achieve what you desire is to use the outer class as a form of namespace and restrict within that class.
No, it is possible. You can use internal class in another assembly.
For example I have a internal string extension class that located in SharMillSoft.Core assembly, if I want use it in another assembly that name is SharpMilSoft.Extension, I must use assembly attribute like as below:
using System;
using System.Linq;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("SharpMilSoft.Extensions")]
namespace SharpMilSoft.Core.Extensions.Strings.Public
{
internal static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return string.IsNullOrEmpty(data);
}
}
}
And I use this class in SharpMilSoft.Extension assembly like as below:
namespace SharpMilSoft.Extensions.Strings
{
public static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return Core.Extensions.Strings.Public.SharpStringExtensions.IsNullOrEmpty(data);
}
}
}
Note: Then SharpMilSoft.Extensions assembly will be friend assembly for SharpMilSoft.Core assembly
For more details about friend assembly, you can visit this link : Friend assemblies
If you have a single assembly you can define as many namespaces in that assembly as you want but no matter what modifier you apply in the IDE you will always be able to see the classes in other namespaces.
Not sure if it is directly possible, but a few good ways to fake it would be:
1) Have the classes that need this sort of stuff inherit from a single class which has the helper class as an internal class.
2) Use extension methods and then only reference the extension methods within the namespace.

Categories

Resources