0

I have a project with some interfaces that contains some type alias in it, for example like below:

namespace UsingTest
{
    using MyType = System.Collections.Generic.List<int>;

    public interface IUsingTest
    {
        MyType GetList();
    }
}

How can I use MyType in another project like below? (without need to redefine type alias)

namespace UsingTest
{
    public class UsingClass : IUsingTest
    {
        public MyType GetList()
        {
            throw new NotImplementedException();
        }
    }
}

Note: if I want write the above code in the same project, as you can see in How do I alias a class name in C#, without having to add a line of code to every file that uses the class?, I need just declare MyType as global using in the interface file. But this technique does not work between multiple projects.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sorosh_sabz
  • 2,356
  • 2
  • 32
  • 53
  • 2
    You *could* simply share the file containing the `global using` between projects (by tweaking the `.csproj`), but it's probably better if you don't do this at all. Either declare a more specific type that is shareable (by wrapping the `List` as a property in another class, for example, or using inheritance, but that's not as appropriate for generic collections) or don't use an alias if the only goal is to save keystrokes (you don't get any more stringent type checking, and `List` is still very general). – Jeroen Mostert Jun 05 '23 at 08:40
  • 1
    It might be a wise choice to make this it's own class. This way you could create a `Core` project which is used by all projects. Inside of this `Core` project you can keep all global additives to your code (think of extension methods for example). This way you can easily manage them/ not pollute te projects themselves – Roe Jun 05 '23 at 08:46
  • 1
    What is the actual problem you are trying to solve? For a list of int, just use `List`. It is not much longer than `MyType`, and it would take much less effort to understand. Lack of global alias *can* be an issue when using much more complicated generic types, but such types tend to be difficult to understand anyway, so might be good to avoid anyway. – JonasH Jun 05 '23 at 09:18
  • @JonasH `List` is just an example, I have some complex generic types, that I want to define well known name for that (`using alias`) and use this name in every where to improve code readability and prevent changing chain, when in main project I change the actual type of that. with `using alias` when I change the actual type, all type in project that change automatically without need to change manually one by one. this approach improve abstraction and decoupling. – sorosh_sabz Jun 05 '23 at 09:47
  • @JeroenMostert Thanks for commenting, but if I share file containing the global using between projects, the problem is naming conflicting, because does not support namespace scope, for example I have using alias foo in Project A and I have using alias foo in Project B, that each of them alias different type (exist in Project A and Project B), if I share files from Project A and Project B into Project C (as user of Project A and Project B) I got a conflicting. – sorosh_sabz Jun 05 '23 at 09:48
  • 1
    If you are having *conflicting* aliases it's almost certainly worth to start using specific classes to represent your types that aren't going to break if the underling generics change. Type aliases were never intended as a feature to support decoupling; they're intended as a stopgap feature to solve the otherwise insoluble problem with different namespaces declaring the same type names. As an abstraction feature they're largely worthless, as the only thing that's happening is a local rename -- the implementation can't change and nowhere is it enforced that only the new name is used. – Jeroen Mostert Jun 05 '23 at 10:39
  • 1
    Once you have a complex generic type like `Dictionary>` or suchlike that isn't memorable on its own it starts paying off to introduce actual classes to represent them, rather than aliases. As a bonus, you can give these more specific names for the methods and properties than the generic methods. You can still fairly easily use the generic collections as the backing storage fields for those classes. – Jeroen Mostert Jun 05 '23 at 10:46
  • @JeroenMostert I do not rename, I change the backend type of `using alias` for example, I `using alias` with `using Foo = List` and some months later I decide to change `using Foo = MyList` in this scenario we do not need change all projects, and all files to replace `List` into `MyList` I just change `using Foo = List` to `using Foo = MyList` and all of thing is working. I think it is abstract real type of Foo from all users. (and it is very worthy). just like all application about awesome `typedef` and `using` keyword in C++ – sorosh_sabz Jun 05 '23 at 10:50
  • @JeroenMostert in many technical situation we can not declare new class or types. for example in many tools like (just example) grpc-code-first, declaring new types cause many boilerplate and redundancy in codes to work well. – sorosh_sabz Jun 05 '23 at 10:52
  • To clarify: `Foo` is just another name for `List`. `Foo` does *not* exist as a type anywhere in the resulting code; any assembly you build with this will use `List` and not `Foo`. It therefore also becomes (confusingly) correct to have `using Foo = List` in project A, compile it, and then do `using Bar = List` in project B, and use everything in A is though it declared `Bar`. This is different from a C and C++ `typedef`, which genuinely defines something new. This is also why your options are limited to sharing files between projects or not using aliases altogether. – Jeroen Mostert Jun 05 '23 at 10:54
  • 1
    Apropros sharing between projects: nothing restricts you to having *one* file containing usings. It would be legal, if a bit tedious, to put `using Foo = List` in its own `Foo.cs`. Applied consistently, this would give you "types" to share as you see fit between projects, with the caveat of course that these are mere aliases, not actual types. Code generation could be used to twiddle namespaces, if having them in the global namespace is not desirable, though at that point I'm not sure just generating whole types wouldn't be more appropriate. – Jeroen Mostert Jun 05 '23 at 10:56

0 Answers0