I got an error today while trying to do some formatting to existing code. Originally, the code had the using directives declared outside the namespace:
using System.Collections.Generic;
namespace MyNamespace
{
using IntPair = KeyValuePair<int, int>;
}
When I tried to insert the using directive inside the statement (to comply with StyleCop's rules), I got an error at the aliasing directive, and I had to fully qualify it:
namespace MyNamespace
{
using System.Collections.Generic;
//using IntPair = KeyValuePair<int, int>; // Error!
using IntPair = System.Collections.Generic.KeyValuePair<int, int>; // works
}
I wonder what difference there is between the two cases? Does the location of the (import-style) using directive matter?
I used to think that it did not matter, but I always fully qualify using commands.
Edit: Checked the C# spec, section 9.4 says that:
The scope of a using-directive specifically does not include its peer using-directives. Thus, peer using-directives do not affect each other, and the order in which they are written is insignificant.
So if System.Collections.Generic and KeyValuePair are treated as peers then KeyValuePair is going to ignore System.Collections.Generic.
Yes, it does - to a small extent. There is an edge-case to do with scoping / local names, see Eric Lippert's blog.
For a concrete example (specific to alias usage):
using System;
using Foo = Bar;
public static class Bar {
public static void Test() { Console.WriteLine("outer"); }
}
namespace MyNamespace {
//using Foo = Bar;
public static class Bar {
public static void Test() { Console.WriteLine("inner"); }
}
static class Program {
static void Main() {
Foo.Test();
}
}
}
Yes it does, I have an working example to a similar question (Namespace collisions).
In essence the rules for name lookup are different if the using directive is global (outside the namespace) or inside the namespace when it takes higher precedence.
This is purely informational, re one of the replies claiming it affects the time that the assembly is loaded; but in reality, assemblies are loaded the first time a method/type using them is JITted (or accessed via reflection, etc).
Here's an example showing it making no difference; with the using in either location, the output is the same: System.Core is loaded as Bar gets JITted:
pre-Bar
System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
pre-Max
Max: 5
post-Max
post-Bar
example (run at command line, not in debugger; ideally in release configuration):
using System;
//using System.Linq;
namespace Foo {
using System.Linq;
class Program {
static Program() {
AppDomain.CurrentDomain.AssemblyLoad += (s, a) => {
Console.WriteLine(a.LoadedAssembly.FullName);
};
}
static void Main() {
Console.WriteLine("pre-Bar");
Bar();
Console.WriteLine("post-Bar");
Console.ReadLine();
}
static void Bar() {
Console.WriteLine("pre-Max");
int[] data = { 1, 2, 3, 4, 5 };
Console.WriteLine("Max: " + Enumerable.Max(data));
Console.WriteLine("post-Max");
}
}
}
Related
So I made a .dll which I added to my project everything works, but when I try to use any of the class from my .dll. I have to specificly use namespace.classname instead of being able to just say Classname even when I put at the top of my project
using namespace
using System;
using MyTestClassLibrary;
using System.IO;
using YangHandler;
namespace UsingMyclassdll
{
class Program
{
static void Main(string[] args)
{
YangHandler.YangHandler yangh = YangHandler.YangHandler.Parse("Rawtext");
Console.ReadKey();
}
}
}
At the line of using Yanghandler visual studio says
Using directive is unnecessary
Isn't this what using is exactly used for to use other namespaces?
YangHandler code
using System;
using System.IO;
namespace YangHandler
{
public class YangHandler
{
public string YangAsRawText { get; private set; }
public static YangHandler Parse(string YangAsRawText)
{
YangHandler handlerToReturn = new YangHandler();
handlerToReturn.YangAsRawText = YangAsRawText;
return handlerToReturn;
}
I know that it could be solved by using namespace aliases under the namespace "UsingMyclassdll" like
using YangHandler = YangHandler.YangHandler;
But isn't there a more normal solution?
Check this very interesting piece of documentation from Microsoft: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-namespaces
DO NOT use the same name for a namespace and a type in that namespace.
For example, do not use Debug as a namespace name and then also provide a class named Debug in the same namespace. Several compilers require such types to be fully qualified.
So your work around is basically defining the fully qualified name as the type and namespace are of the same name.
No work around for this. The compiler can't know if you mean the one or the other.
I am having a DLL file. With the use of DLL, I have to call the methods and add some more methods in my project. Now, I need to migrate the older DLL to Make that project as a new DLL. I done this But the problem is The C# code is converted to net module it shows two errors. I am not clear about that. kindly help me over it.
DLL Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace mcMath
{
public class mcMathComp
{
private bool bTest = false;
public mcMathComp()
{
// TODO: Add constructor logic here
}
/// <summary>
/// //This is a test method
/// </summary>
public void mcTestMethod()
{ }
public long Add(long val1, long val2)
{
return val1 - val2;
}
/// <summary>
/// //This is a test property
/// </summary>
public bool Extra
{
get
{
return bTest;
}
set
{
bTest = Extra;
}
}
}
}
CS Project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using mcMath;
namespace mcClient
{
class Program
{
static void Main(string[] args)
{
mcMathComp cls = new mcMathComp();
long lRes = cls.Add(23, 40);
cls.Extra = false;
Console.WriteLine(lRes.ToString());
Console.ReadKey();
}
}
}
Errors:
Program.cs(5,7): error CS0246: The type or namespace name 'mcMath' could >not be found (are you missing a using directive or an assembly reference?)
Tried Methods:
I will add the reference via Project-> Add Reference.
The using Reference also used.
Put the DLL into the current project debug/release folder
I'm guessing you used to have the code side by side, i.e.
public int Add(int a, int b)
{
return a + b;
}
public void SomeMethod()
{
var result = Add(2,3);
}
This works because the scope (this.) is applied implicitly, and takes you to the Add method on the current instance. However, if you move the method out, the scope is no longer implicit.
You will need one of:
the type name if it is a static method
or a static using if using C# 6
a reference to the instance if it is an instance method
Then you would use one of (respectively):
var result = YourType.Add(2,3); (plus using YourNamespace; at the top)
using static YourNamespace.YourType; at the top
var result = someObj.Add(2,3);
Checking the compiler message, it sounds like you've done something like (line 7):
using YourNamespace.YourType.Add;
which is simply wrong; you don't use using to bring methods into scope - only namespaces and (in C# 6) types.
Likewise, I suspect you have (line 22):
var result = YourNamespace.YourType.Add(x,y);
which is not valid as this is not a static method.
Create and Using DLL in same Project in c#
DLL or Class Library is a separate project that can be part of same solution.
As you already know, adding a reference to that dll/project will make it available in your app project.
However if function Add in dll is in different namespace (which would be normal) u would need to add using clause at the beginning of your class
I suspect this is a question which has been asked many times before but i haven't found one.
I normally use fully qualified namespaces if i don't use that type often in the file or i add using namaspacename at the top of the file to be able to write new ClassName().
But what if only a part of the full namespace was added ? Why can't the compiler find the type and throws an error?
Consider following class in a nested namespace:
namespace ns_1
{
namespace ns_1_1
{
public class Foo { }
}
}
So if i now want to initialize an instance of this class, it works in following ways:
using ns_1.ns_1_1;
public class Program
{
public Program()
{
// works, fully qualified namespace:
var foo = new ns_1.ns_1_1.Foo();
// works, because of using ns_1.ns_1_1:
foo = new Foo();
}
}
But following doesn't work:
using ns_1;
public class Program
{
public Program()
{
// doesn't work even if using ns_1 was added
var no_foo = new ns_1_1.Foo();
}
}
it throws the compiler error:
The type or namespace name 'ns_1_1' could not be found (are you
missing a using directive or an assembly reference?)
I assume because ns_1_1 is treated like a class which contains another class Foo instead of a namespace, is this correct?
I haven't found the language specification, where is this documented? Why is the compiler not smart enough to check if there's a class or namespace(-part)?
Here's another - less abstract - example of what i mean:
using System.Data;
public class Program
{
public Program()
{
using (var con = new SqlClient.SqlConnection("...")) // doesn't work
{
//...
}
}
}
Edit: now i know why this seems very strange to me. It works without a problem in VB.NET:
Imports System.Data
Public Class Program
Public Sub New()
Using con = New SqlClient.SqlConnection("...") ' no problem
End Using
End Sub
End Class
This obvious way unfortunately not working but you can make all this by an alias namespace:
using ns_1_1 = ns_1.ns_1_1;
public class Program
{
public Program()
{
var no_foo = new ns_1_1.Foo();
}
}
The documentation says:
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.
So the using only includes the types (not the namespaces) that are defined in the specified namespace. In order to access types of nested namespace you need to specify it explicitly with a using directive as you did in your first example.
This is documented in the standard in 3.8 Namespace and Type Names, but it's a bit convoluted to follow.
The gist of it that a partial namespace reference is only looked for in the namespace where it occurs, and each layer outwards. using-directives are not checked.
In your example, ns_1_1.Foo would be found if Foo is found anywhere in:
Program.Program.ns_1_1.Foo
Program.ns_1_1.Foo
ns_1_1.Foo
Partial namespaces will work only if your current class is part of that partial namespace. Using statements are not considered for accessing types through partial namespace.
For instance this will work because your current namespace is ns_1
namespace ns_1
{
public class Program
{
public Program()
{
var no_foo = new ns_1_1.Foo();
}
}
}
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.
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 ?