Why do extension methods not work with namespace aliasing? - c#

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.

Related

How to avoid having to write namespace before class C#

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.

Why is the class not accessible in unit test?

I have created a unit test for a method in a class called game.cs. For some reason, when I reference the class, I am unable to create a new instance. How do I make this class accessible so I can test my code?
File Hierarchy and solution:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BowlingKataTDD;
namespace BowlingKataTDDTest
{
[TestClass]
public class BowlingKataTDDUnitTests
{
[TestMethod]
public void DoesGameExist()
{
//arrange
BowlingKataTDD.
}
}
}
BowlingKataTDD Project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BowlingKataTDD
{
class Game
{
static void Main(string[] args)
{
}
}
}
The reason you do not see the classes is that they are non-public (internal by default).
There are two solutions to this:
If you would like to make your classes visible to outside users, make them public
If you would rather not publish your classes, use InternalsVisibleTo attribute.
To use the second solution, open AssemblyInfo.cs and add the following line:
[assembly: InternalsVisibleTo("BowlingKataTDDTest")]
BowlingKataTDDTest is the name of your assembly, as defined in the project file.
Make the class public, as well as any members of that class which need to be invoked externally (such as by a unit test):
public class Game
{
public static void Main(string[] args)
{
}
}
This is a common mistake with calling libraries with new projects, and I was able to resolve it. Often easy to forget to change the modifier to public from the project in Visual Studio, because by default a new project template creates the class though without it being set to public. When changing the Game class to public, am able to instantiate the Game object.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BowlingKataTDD;
namespace BowlingKataTDDTest
{
[TestClass]
public class BowlingKataTDDUnitTests
{
[TestMethod]
public void DoesGameExist()
{
//arrange
BowlingKataTDD.Game game = new BowlingKataTDD.Game();
}
}
}

Extension Methods with Custom Classes

I'm attempting to extend my custom classes and running into a problem where it cannot find the extension method.. I have and can extend any built in classes or even ones contained within DLL's. I don't know if this is a compilation error or if I'm doing something wrong. Threw together a small program for an example, won't compile..
Here's the extension:
namespace ExtensionMethodTesting.Extension
{
public static class Extension
{
public static void DoSomething(this ExtensionMethodTesting.Blah.CustomClass r)
{
}
}
}
Here's the Custom Class:
namespace ExtensionMethodTesting.Blah
{
public class CustomClass
{
public static void DoNothing()
{
}
}
}
Here's the code calling it:
using ExtensionMethodTesting.Blah;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ExtensionMethodTesting.Extension;
namespace ExtensionMethodTesting
{
class Program
{
static void Main(string[] args)
{
CustomClass.DoNothing();
CustomClass.DoSomething();
}
}
}
I must be missing something... Anyways the exact error just for clarification is:
Error 1 'ExtensionMethodTesting.Blah.CustomClass' does not contain a definition for 'DoSomething' c:\users\damon\documents\visual studio 2013\Projects\ExtensionMethodTesting\ExtensionMethodTesting\Program.cs 16 25 ExtensionMethodTesting
Extension methods require an instance of an object. You'll have to new up a CustomClass to use it.
var custom = new CustomClass();
custom.DoSomething();
See this answer as to why that is.
You need to instantiate an object of the CustomClass to use its extension method.
CustomClass obj = new CustomClass();
obj.DoSomething();

Namespace issue with period

I have a class:
namespace FooIOS
{
public class Foo
{
public static void doThis() {...}
}
}
And this works:
using FooIOS;
namespace Sample.iOS
{
public void method () {
Foo.doThis();
}
}
However, this does not work the same way when I change the namespace to insert a period:
namespace Foo.iOS
{
public class Foo
{
public static void doThis() {...}
}
}
using Foo.iOS;
namespace Sample.iOS
{
public void method () {
// Compilation error
Foo.doThis();
// Compilation error
Foo.iOS.doThis()
// This works but I can't have it that long and complicated (I'm writing an API call)
Foo.iOS.Foo.doThis();
}
}
I'm pretty inexperienced with C# and I'm wondering if there's any way to use the period in the namespace and not deal with the complicated call.
namespace Foo.iOS
{
public class Foo
{
public static void doThis() {...}
}
}
Your namespace name is Foo.iOS, class name is Foo, static method name is doThis(). The fully qualified path to access that method is NAMESPACE.CLASS.METHOD_NAME, so it becomes:
Foo.iOS.Foo.doThis();
Here is nothing wrong with C#, but with the naming you use.
From this a couple of suggestions:
try to no use . inside names of the namespace, as this introduces confusion
try to not name namespace as the class inside it, as this introduces confusion.
I'm pretty inexperienced with C# and I'm wondering if there's any way
to use the period in the namespace and not deal with the complicated
call.
Short answer is: name your namespaces, classes and member functions in a way, that it does not look complicated to you and to others.
EDIT
Consider that you can use also Namespace Alias.
For example:
using IOS = Foo.iOS;
...
IOS.Foo.doThis();
But as I said before, it's better to avoid . in namespace name at first place.
Bring the using Foo.iOS; statement inside the namespace Sample.iOS namespace block, like shown below, then you will be able to call doThis() like in your 1st attempt Foo.doThis(); that was previously giving you a compile error.
namespace Sample.iOS
{
using Foo.iOS;
public void method () {
// this works
Foo.doThis();
}
}
Related reading: Inside or Outside? by Eric Lippert on MSDN.
Fully working Code sample:
Create a new Console App in Visual Studio, and then in the Program.cs class, delete all lines, paste the following, do a compile and then run.
using System;
namespace Foo.iOS
{
public class Foo
{
public static void doThis() { Console.Write("Inside doThis");}
}
}
namespace Sample.iOS
{
using Foo.iOS;
class Program
{
static void Main(string[] args)
{
method();
Console.ReadKey();
}
public static void method ()
{
// works fine
Foo.doThis();
}
}
}

Namespaces in C# Same Project

I have a static class like so:
namespace Engine.Configuration
{
public static class Configuration
{
public static int i;
}
}
In the same project, but a different namespace I have a class trying to access the static class variable:
namespace Engine.MainProgram
{
public class MainProgram
{
int x;
int y;
public void LoadConfiguration()
{
x = Configuration.Configuration.i;
}
}
}
What I would like to do is just place a using statement in MainProgram like so:
using Engine.Configuration;
...
x = Configuration.i;
But when I try to visual studio always treats Configuration as a namespace instead of the static class. My question is why does this happen and how do I correct this?
Try:
using A = Engine.Configuration;
then
x = A.Configuration.i;
or just use
x = global::Engine.Configuration.Configuration.i
The compiler doesn't always know how to distinguish between a namespace and a class name with the same name.
Change this:
using Engine.Configuration;
To a namespace alias:
using Configuration = Engine.Configuration.Configuration;
Explenation:
Let's say you are working directly under the root namespace, Engine, like so:
namespace Engine
{
}
Then you could get things in other namespaces like this:
namespace Engine
{
Engine.Configuration.Configuration;
// Or since you are in the root (Engine) you don't need to specify Engine:
// You can always omit the root namespace if the namespace you're in has the same root.
Configuration.Configuration;
}
Or by declaring a using for the namespace, but the compiler won't know if you mean the namespace or the class in the namespace:
using Engine.Configuration;
namespace Engine
{
// This will still work.
Engine.Configuration.Configuration;
// This will break, do we mean "Engine.Configuration.Configuration" or "Engine.Configuration"?
Configuration;
}
So it's a good practice to never have the same name for a class as the namespace it lives in. Maybe change the namespace to Engine.Configurations.

Categories