118

One feature of Pascal I found very useful was the ability to name a data type, eg

type
 person: record
             name: string;
             age: int;
         end;

var
 me: person;
 you: person;

etc

Can you do something similar in C#? I want to be able to do something like

using complexList = List<Tuple<int,string,int>>;

complexList peopleList;
anotherList otherList;

So that if I have to change the definition of the datatype, I can do it in one place.

Does C# support a way to achieve this?

juergen d
  • 201,996
  • 37
  • 293
  • 362
haughtonomous
  • 4,602
  • 11
  • 34
  • 52

6 Answers6

153

Yes, it's possible. Working example here. You can write:

using System;
using System.Collections.Generic;

namespace ConsoleApplication12
{
    using MyAlias = List<Tuple<int, string, int>>;
}

or, if declared outside the namespace:

using System;
using System.Collections.Generic;

using MyAlias = System.Collections.Generic.List<System.Tuple<int, string, int>>;

namespace ConsoleApplication12
{
}

then use it as a type:

MyAlias test = new MyAlias();
Jodrell
  • 34,946
  • 5
  • 87
  • 124
ken2k
  • 48,145
  • 10
  • 116
  • 176
  • 2
    have you tried this? it will not compile (assuming `List` is the typical one); a `using` alias always requires the full namespace to be specified. – Marc Gravell Feb 13 '12 at 09:36
  • 2
    @MarcGravell Of course I tested it, it definitely compiles and works fine. – ken2k Feb 13 '12 at 09:45
  • 1
    @MarcGravell Precision: it works fine if it's declared inside the `namespace` scope. Updating the answer. – ken2k Feb 13 '12 at 09:47
  • @MarcGravell, and, if all the `using`s are inside the `namespace`, which seems to be the prevailing style. The full name must be specified. – Jodrell Feb 06 '13 at 09:29
  • 3
    @Jodrell I very rarely see `using` directives inside the `namespace`, mainly because that is not where most tools put them. – Marc Gravell Feb 06 '13 at 10:20
  • @MarcGravell Indeed, even Visual Studio templates put them outside. One tool that wants them to be inside is Stylecop (rule SA1200, see http://stylecop.soyuz5.com/SA1200.html). – ken2k Feb 06 '13 at 10:50
  • for additional reference http://stackoverflow.com/questions/125319/should-usings-be-inside-or-outside-the-namespace – Jodrell Feb 06 '13 at 11:14
  • Is there any scoping reason to put them inside the namespace? It doesn't seem to affect scoping outside of the file, so I can only think that it would be a scoping issue if you had multiple namespaces in one file. – jocull Feb 09 '17 at 18:05
  • 9
    @ken2k can you export MyAlias and used it in other source files? How do you do that? – gen Sep 01 '17 at 09:27
  • 7
    Why is this not the accepted answer? This actually provides the solution to the question – AustinWBryan May 31 '18 at 07:08
71

It's not excatly what you do in Pascal, but you can use the using-directive. Have a look here on how to use it

Example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MyList = Dummy2.CompleXList;

namespace Dummy2
{
    public class Person 
    {
    }

    public class CompleXList : List<Person> 
    { 
    }


    class Program
    {
        static void Main(string[] args)
        {
            MyList l1 = new MyList();
        }
    }
}
Mithrandir
  • 24,869
  • 6
  • 50
  • 66
  • 32
    minor point: the `using` at the top of a file are **directives**, not **statements**; the "using statement" is the thing involving `IDisposable`. In particular, this is a "using alias". – Marc Gravell Feb 13 '12 at 09:37
  • 2
    Of note: Also if you just name the class "MyList", the using directive is of course no longer required (and that also solves the original problem). – BrainSlugs83 Oct 20 '13 at 23:07
  • The link points to an older documentation page. While still active and accurate (and has the below link in it) here is the link to the newer page should the old page get removed. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-directive – MadCityDev Dec 27 '17 at 22:14
  • 2
    Does this work for named tuples somehow? I can't make it work. What I try is this: `using MyType = (TypeA a, TypeB b);`. I guess I could use unnamed tuples and it would work, but I really want the names and not `Item1`, `Item2`. :( – user2173353 Feb 14 '19 at 09:51
  • In the newest versions, use `global using = ...` to work across multiple files. – Ferazhu Nov 13 '22 at 11:23
19

You can create a type:

class ComplexList : List<Tuple<int,string,int>> { }

This is not strictly the same as an alias but in most cases, you shouldn't see any differences.

Serge Wautier
  • 21,494
  • 13
  • 69
  • 110
8

From the syntax shown in the initial question, it looks like you're really just asking how to make a class in C#, and not how to alias a type.

If you want a simpler name to type than List<Tuple<int,string,int>>, and you want it to be "global" (i.e. not per-file), I would create a new class that inherited said class and declared no additional members. Like this:

public class MyTrinaryTupleList: List<Tuple<int,string,int>> { }

That gives one single location of management, and no need for additional using statements.

However, I would also take it a step further, and venture that you probably don't want a Tuple, but rather another class, such as:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public int FavoriteNumber { get; set; }

    public Person() { }

    public Person(string name, int age, int favoriteNumber) 
    { 
        this.Name = name; 
        this.Age = age; 
        this.FavoriteNumber = favoriteNumber; 
    }
}

And then for your list type you can do the following:

public class PersonList: List<Person> { }

In addition, if you need other list specific helper properties or methods you can add them to the PersonList class as well.

BrainSlugs83
  • 6,214
  • 7
  • 50
  • 56
8

Yes you can do that, however you need to specify the full types, i.e. the definition becomes:

using ComplexList = System.Collections.Generic.List<System.Tuple<int,string,int>>;

This is specified per file, much like the using directives for namespaces.

nitpick: Conventionally, a type in .NET is PascalCased.

flq
  • 22,247
  • 8
  • 55
  • 77
  • "Full types" are not required. If other `using` (such as `using System.Collections.Generic;` are present), then "full types" are not necessary. – ken2k Feb 13 '12 at 09:25
  • 2
    @ken2k incorrect; a `using` alias always requires it to be namespace-qualified explicitly, **even if** the existing `using` directives would bring it into scope; meaning: `using var list = List;` is **not** valid, even after `using System.Collections.Generic;` – Marc Gravell Feb 13 '12 at 09:35
  • 1
    It's not required if the alias is defined inside the scope of a namespace, actually. – ken2k Feb 13 '12 at 09:50
4

Just a simple using would do:

using Foo = System.UInt16;

public class Test {
  public Foo Bar { get;set; }
}
juFo
  • 17,849
  • 10
  • 105
  • 142