52

Since I am using two different generic collection namespaces (System.Collections.Generic and Iesi.Collections.Generic), I have conflicts. In other parts of the project, I am using both the nunit and mstest framework, but qualify that when I call Assert I want to use the nunit version by

using Assert = NUnit.Framework.Assert;

Which works great, but I want to do the same thing with generic types. However, the following lines do not work

using ISet = System.Collections.Generic.ISet;
using ISet<> = System.Collections.Generic.ISet<>;

Does anyone know how to tell .net how to use the using statement with generics?

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Jason More
  • 6,983
  • 6
  • 43
  • 52
  • 6
    This is an occasionally requested feature. It's been on the list of possible features for a long time, but has never been high enough priority to actually implement. – Eric Lippert Sep 15 '10 at 18:12
  • Eric, this is the first time I've run across this issue, since the .net 4.0 framework added ISet<>, and the Iesi.Collections dll targets 3.5. Usually other developers are good about not conflicting with the standard .net naming. – Jason More Sep 17 '10 at 13:01
  • 2
    Why do you have it in two different namespaces? Can you provide more information? – David L Mar 12 '13 at 18:18
  • I'd phrase that differently. Intentionally using the same name for two different things is going to be inconvenient. This works best if you are extremely unlikely to be `using` the two namespaces simultaneously. – Roman Starkov Mar 12 '13 at 18:28
  • @EricLippert When converting code from Java or Haskell or other languages that supports precise symbol import (i.e. `import myModule.MyClass;` in Java, I found this is a major defect of C# because you have to `using` everything from `System.Collections.Generic` even when you only need `IEnumerable<>` for your LINQ expression. Java is not allow renaming but I think import renaming is is actually "occasionally" requested, not precise import/using. – Earth Engine Feb 12 '14 at 04:55

6 Answers6

52

Unfortunately, the using directive does not do what you want. You can say:

using Frob = System.String;

and

using ListOfInts = System.Collections.Generic.List<System.Int32>;

but you cannot say

using Blob<T> = System.Collections.Generic.List<T>

or

using Blob = System.Collections.Generic.List

It's a shortcoming of the language that has never been rectified.

Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
45

I think you're better off aliasing the namespaces themselves as opposed to the generic types (which I don't think is possible).

So for instance:

using S = System.Collections.Generic;
using I = Iesi.Collections.Generic;

Then for a BCL ISet<int>, for example:

S.ISet<int> integers = new S.HashSet<int>();
Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • Very nice suggestion! Had the exact same problem just now and this did not immediately occur to me. – julealgon Dec 20 '13 at 20:36
  • 1
    That only works if it's the namespace that's the long bit. If the type parameters themselves have lengthy type names, you're out of luck. – Drew Noakes Aug 06 '16 at 13:21
  • Just ran into the same problem. I want to use constants defined in a generic class as default parameter values for a constructor and there are 4 of them, so I have to type the full, lengthy class name out, with it's generic parameters, plus the constant name. This could be solved if the language allowed using statements _inside_ the generic class, like `using C = Long.Name`. Outside the class, the generic parameters are unkknown, so it's not useful. – Triynko Apr 23 '20 at 23:05
7

The only way you can alias a generic type is to specialize it as follows.

using IntSet = System.Collections.Generic.ISet<int>;

You can not alias an open generic type as you have done in your example:

using MySet = System.Collections.Generic.ISet<>;
Steve Guidi
  • 19,700
  • 9
  • 74
  • 90
3

Your alias name is the same as the class name itself, so you still have ambiguity, just as if you had a using for each namespace. Give the alias of the class a different name, i.e.:

using FirstNamespace;
using OtherObject = SecondNamespace.MyObject;

public class Foo
{
    public void Bar()
    {
        MyObject first = new MyObject;//will be the MyObject from the first namespace
        OtherObject second = new OtherObject;
    }
}
Servy
  • 202,030
  • 26
  • 332
  • 449
1

In some cases you can go with inheritance:

public class MyList<T1, T2> : List<Tuple<IEnumerable<HashSet<T1>>, IComparable<T2>>> { }

public void Meth()
{
    var x = new MyList<int, bool>();
}
Dan Atkinson
  • 11,391
  • 14
  • 81
  • 114
Mike Tsayper
  • 1,686
  • 1
  • 17
  • 25
0

You can alias a class doing :

using Test = NameSpace.MyClass;

Only if the class is NOT generic.

Samuel Slade
  • 8,405
  • 6
  • 33
  • 55
Thomas
  • 5,603
  • 5
  • 32
  • 48
  • 4
    You *can* alias a generic class, you just need to specify a concrete type in the alias, rather than leaving it generic. – Servy Mar 12 '13 at 18:25