Okay, so I've been reading a book on C# and .NET, and while learning about the DateTime structure and the following code:
DateTime dt = new DateTime(2015, 10, 17);
I asked myself "why didn't I have to reference it at the top by writing using System.DateTime"?
So I realized that since DateTime is a structure, and the "using" keyword is used to reference types (type being a general term to refer to a member from the set {class, interface, structure, enumeration, delegate}), defined in a particular namespace (in this case, DateTime is of type structure from the System Namespace).
But I noticed that at the top of my file, the following using directives are found (they were put there automatically when I created my C# console application):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
I was wondering why the using directives that follow using System were necessary, when aren't they all under the System namespace and therefore they should already be referenced?
So I'm guessing it's because all the ones declared below it are namespaces, as opposed to a type from the set {class, interface, structure, enumeration, delegate}. But would it be wrong to refer to them as "namespaces OF (or belonging to) the namespace System," and if so, what is the reason that you must explicitly reference namespaces of a namespace instead of them being implicitly included under using System?
I hope my question was clear but if not, please let me know so I can edit it.
Internally, all .net types always have full type names;
System.DateTime
System.Collections.Generic.Dictionary<string, int>
System.Threading.Tasks.Task
what the 'usings' do is to let you refer 'invisibly' to everything before a '.' character. So when you write
DateTime
C# will try
System.DateTime
System.Collections.Generic.DateTime
System.Linq.DateTime
System.Text.DateTime
etc...
Since only one exists (System.DateTime) it's an unambiguous match, and C# knows what you're talking about.
If there were two matches, you'd get a compiler error about the ambiguity. So if there were a System.Threading.Task.DateTime, your program wouldn't compile.
All this sets the scene for the answer to your question. If
using System;
included everything below it, then it would be hard to ensure that things aren't ambiguous. For example, if you wanted to differentiate between two theoretical classes
System.WebPages.Button
System.Desktop.Button
then a plain old using System wouldn't play nice with new Button().
The reason is that if it weren't that way, you'd have no way of avoiding unwanted name collisions in certain circumstances. For instance, if you had a type Baz in Foo namespace and a type Baz in Foo.Bar namespace, you'd always have to fully-qualify your types, e.g. Foo.Baz or Foo.Bar.Baz, in your code, which would make the using directives pointless.
Given the way it is, you only have to deal with name collisions if you actually have using directives for both namespaces that contain your type.
You don't have to have other using directives, e.g. if you wanted a List you could just declare in your code:
System.Collections.Generic.List<String> listOfStrings = new System.Collections.Generic.List<String>;
To create a new List, but the using statement lets you simply declare it as:
List<String> listOfStrings = new List<String>;
The reason you can't do the latter with only:
using System;
Is because there could be a class in System called List, as well as the List class in System.Collections.Generic. If so, when you create a new list object, how does it know which List class you're referring to?
So essentially they're used to prevent naming conflicts, and to enable programmers to group things into logically named groups, e.g. input and output related classes can be found in System.IO
Create a using directive to use the types in a namespace without having to specify the namespace. A using directive does not give you access to any namespaces that are nested in the namespace you specify.
from
https://msdn.microsoft.com/en-us/library/sf0df423.aspx
The same thing happens when I am assigned namespaces cause of my folder structure like projectName\Code\DBFiles if I do using Code; on one of my controllers it doesn't give me access classes in DBFiles that's why I set all my class name spaces to the root namespace.
Related
I've got an issue when importing a package/library that introduces namespace Math.Native.Gmp (it's called "Math.Gmp.Native" on NuGet).
Before import, this code works perfectly fine:
using System;
namespace Sample
{
public int Foo()
{
return Math.Min(1, 2);
}
}
After adding this reference, however, Math is no longer recognized as a System.Math, but is hidden by the newly added namespace - Math. expects only Math.Native as the correct extension of the path.
Trying to use Math.Min ends up with compiler error:
[CS0234] The type or namespace name 'Min' does not exist in the namespace 'Math' (are you missing an assembly reference?)
I found out that original Math is still accessible via System.Math, so in the example above, after adding this prefix (return System.Math.Min(1, 2);) everything works as intended. It is some walkaround
My question is - how to avoid that overshadowing of Math? Can I use some using commands at the beginning of the file to avoid it?. Can I make some alias for Math.Native.Gmp namespace so that it won't be conflicting with System.Math?
As described in the documentation of the using statement you can use something like
using myMath = System.Math;
to define an alias for a namespace.
There IS a way to resolve this conflict by moving Math.Gmp.Native namespace away. That can be done by setting an alias to that library. In .csproj file of our project set ("Gmp" is just a selected name by me):
<PackageReference Include="Math.Gmp.Native.NET">
<Aliases>Gmp</Aliases>
</PackageReference>
In that way Math.<xyz> no longer means things from that library, but - as intended - from System.Math.
In files where you want to use the imported library, you have to include:
extern alias Gmp;
using Gmp::Math.Gmp.Native;
It won't create conflicts either!
HUGE WARNING: This solution has a massive drawback. When you want to use this project in your second project, the second project will have exactly the same issue. Although Math.Gmp.Native.NET is a just nested reference, it causes the same overshadowing of the Math namespace.
So, in every project using Math.Gmp.Native.NET anywhere in a tree of references, Math is overshadowed by the library's one. If you want to use Math there as the default System.Math, you got to include in its .csproj same code shown above.
It gets messy and hard to follow why Math doesn't work without that magic reference in the .csproj file in the project not even using (directly) anything from this library. That is why I haven't chosen this answer as an accepted one
To build up on alrady given answer:
whenever you have this conflict, System.Math was there first. So to make things working again use in every file using statement:
using Math = System.Math;
If you want to use the other namespace easily, you can rely here on #MarkusSafar answer and use some custom alias:
using OtherMath = /*other math namespace*/;
or just use fully qualified names.
I have a library project in my solution that I just added, and whenever I need to reference a class/enum I have to use:
using global::MyName.SubName;
(Resharper automatically suggests this)
Why is this? Why can't I just do:
using MyName.SubName;
Which doesn't work. And even when it does this I am getting this error:
Error 400 Member 'MyName.SubName.Enumerations.SomeEnum.SomeEnumName1' cannot be accessed with an instance reference; qualify it with a type name instead
I can only assume your MyName.SubName being hid (same name) by something else.
See the following MS article for more info: How to: Use the Global Namespace Alias
I think it explains the scenario you are running into.
The ability to access a member in the global namespace is useful when
the member might be hidden by another entity of the same name.
...
However, in larger projects, it is a very real possibility that
namespace duplication may occur in one form or another. In these
situations, the global namespace qualifier is your guarantee that you
can specify the root namespace.
I agree with #kelsey that it looks like a namespace conflict. Another way to resolve it is to use namespacing aliasing like;
using MNSub = MyName.SubName
// ...else where in code
MNSub.MyType varName = new MNSub.MyType(); // etc.
This at least gives a more meaningful syntax than global::...
.NET Documentation for 3.5 Collections.Generic.SortedList
In the documentation, it plainly states that "ElementAt" is an extension method on SortedList members. Well, I've got one, declared thusly:
private SortedList<int, ChainLink> linksByLevel = new SortedList<int, ChainLink>();
I try to get the last element:
ChainLink lastLink = linksByLevel.ElementAt(linksByLevel.Count - 1);
The compiler throws the massively helpful message:
Error 1 'System.Collections.Generic.SortedList' does not contain a definition for 'ElementAt' and no extension method 'ElementAt' accepting a first argument of type 'System.Collections.Generic.SortedList<int,ChainLink>' could be found (are you missing a using directive or an assembly reference?)
I'm getting pretty frustrated by the lack of coherence in Microsoft's documentation and my compiler and would love to rant about the inconsistencies between the APIs for SortedList and SortedList<T1, T2>, but I doubt that would add much value to my question. Just trust me, it's frustrating :-\
Try adding an import to the top of your code file:
using System.Linq;
You need to specify that you're using the namespace containing the extension method before you can actually use the extension method. So, as the error explained, you were missing a using-directive.
If you do know that the method is an extension method, but you don't know in which namespace it lives, then you'll probably need to search online to find it. Visual Studio 2012 by default cannot resolve it for you. The extension method you are talking about is Enumerable.ElementAt in the System.Linq namespace of System.Core.dll.
In Visual Studio, when you create a new class file, you'll have using System.Linq inserted at the top automatically. That namespace contains all the LINQ extension methods for working with all kinds of collections (including lists, dictionaries and arrays).
Did you add
using System.Linq;
at the top of your file?
W.R.T. documentation inconsistency, if you look at the SortedList docs, and click through to ElementAt, you'll clearly see at the top of the page that you need to include System.Linq.
SortedList and SortedList<K,V> are very different beasts.
The older SortedList uses an array under the covers and so it can provide an efficient indexer.
Beware that when you use the extension method ElementAt() it will probably do a 'tablescan', don't use it for something time-critical.
I don't even know if it's called an alias, but let me continue anyway.
You know how the System.String type in C# is sorta "aliased" with "string"? In Visual Studio, "string" is in lowercase and blue text. I'd like to do this to some of our lengthy class names. Some are all like "RelocatedPlantProductReleaseItem". I can't change the name of it, but such a long name really makes the code long-winded. I'd like to be able to use "Rppr" instead. So instead of this:
RelocatedPlantProductReleaseItem Item = new RelocatedPlantProductReleaseItem();
I'd go like:
Rppr Item = new Rppr();
I know that I can create a class called Rppr and have it inherit from RelocatedPlantProductReleaseItem, but that seems hacky.
Also, the scenario I gave above is totally fictitious. I just used it to demonstrate the essential functionality I am trying to achieve.
Also, what is it technically called when "string" represents System.String?
I want this to be a global thing. I don't want to have to specify it at the top of every code file. I want to specify it in one place and it work everywhere in the entire application, even in other assemblies that reference its assembly.
Use a using directive
using Rppr = Namespace.To.RelocatedPlantProductReleaseItem;
EDIT Op clarified to ask for a global solution.
There is no typedef style equivalent in C# which can create a global replacement of a type name. You'll need to use a using directive in every file you want to have this abbreviation or go for the long version of the name.
string is a convenience offered by the C# language to refer to the actual CLR type System.String.
You can achieve similar results with a using directive. At the top of the file where you'd like the name shortened, add this line:
using ShortName = Namespace.ReallyLongClassNameGoesHereOhGodWhy;
Then you can say ShortName myVar = new ShortName();
Note that you have to do this on a per file basis. You can't get the same coverage as string with a single declaration.
Try
using Rppr = SomeNamespace.RelocatedPlantProductReleaseItem;
Reference
You can do this :
using Rppr = RelocatedPlantProductReleaseItem;
You create an alias using:
using alias = LongClassName;
That alias is visible in the namespace where you declared it.
You can add a using directive at the top of your file:
using Rppr = MyProjectNs.RelocatedPlantProductReleaseItem;
But it (only) works per file, not for a Project.
try to add the following with your other usings
using Rppr = YourItemsNamespace.RelocatedPlantProductReleaseItem;
As of C#10, it is now possible to do this globally by using the global modifier.
global using Rppr = Namespace.To.RelocatedPlantProductReleaseItem;
This can be added to any file in the compilation and then applies to all other files, but must be added before any using directives that do not have the global modifier.
I tried the following
// no using statements here, not even using System;
class Program
{
static void Main(string[] args)
{
string[] arr = new string[3] { "A" , "B", "C" };
}
}
My question is simple, even without any using statements, how come compiler is able to compile this, more specifically, shouldn't there be a compile time error because I am trying to build an array and System.Array is not accessible?
Thanks.
You seem to have a misunderstanding about what using means. A using directive is for determining what a simple name means in your program at compile time. When you say using Foo; that means "if the text of this program uses the simple name Bar, and it doesn't seem like anything named Bar is in scope where the name is used then try checking to see if there is a type called Bar inside namespace Foo".
Your program does not contain any simple names! (string is not a simple name; it is a keyword of the language.) Therefore there is no need to have any using directive to resolve the non-existing simple names.
using does not at all mean "this program uses features that require types found in this assembly", which is what you seem to think it means. using directives are only about (1) simple name resolution, and (2) extension method name resolution.
Arrays are part of the language. You don't need to reference a namespace to use them.
string[] will translate to System.Array while compiling. Since its already fully qualified, it doesn't need any using statements.
You're not referring by name to any namespaced type but yours (the Program class).
string and [] are aliases that are indeed equivalent to System.String and System.Array respectively, but using them does not require pulling their counterparts' namespaces into scope.
You aren't directly referencing the Array class or its members, so the compiler won't complain that you're trying to reference an unused namespace or type. You're just using notation that's part of the C# language itself to make arrays.
This is because you are using core things, you don't even need System for this to compile. The System namespace has extended functionality, some of the classes included in the System Namespace is:
Action
Func
Console
And many more..
As you are not trying to write something to the command prompt, creating actions or even asking for date using DateTime, you don't need to import anything.
using statements do not include anything or provide any ekstra code. It only makes it simplier to code, because you don't have to write the whole path every time.
string automatically converts to System.String.
You can write this:
class Foo {
string Bar() {
return System.IO.File.Exists("path").ToString();
}
}
or just
using System.IO;
class Foo {
string Bar() {
return File.Exists("path").ToString();
}
}
both compiles to the same program.
Namespaces are not necessary, you can organize with namespaces your code but you don't have to.
And common keywords are automatically referenced to the proper namespace.
For better understanding read this msdna document http://msdn.microsoft.com/en-us/library/ms973231.aspx