Git Product home page Git Product logo

Comments (15)

ulln avatar ulln commented on July 17, 2024 8

Most of the time, types in different namespaces are (and IMO should be) loosely coupled and a "namespace internal" access modifier would definitely help to achieve that.

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024

The CLR doesn't provide special accessibility like that. It only works from nested type back to parent type(s).

Also, the use of public nested types in this fashion is explicitly against the language design patterns:

https://msdn.microsoft.com/en-us/library/ms229027.aspx

It's more appropriate to define a public top-level interface and have a private nested implementation.

from csharplang.

benaadams avatar benaadams commented on July 17, 2024

It's more appropriate to define a public top-level interface and have a private nested implementation.

Could work though my use case would be for a struct so interface would box. Alternative would be for separate type and use internal

public class Thing
{
    private ThingsThing _thing;

    public ThingsThing MyThing => _thing;
}

public struct ThingsThing
{
    public object Stuff { get; internal set; }

    public void DoThings();

    internal void DoThatThing();
}

But then it has assembly level visibility rather than class level 😿

from csharplang.

benaadams avatar benaadams commented on July 17, 2024

Maybe a assembly namespace level visibility would work, so internal but scoped to namespace for tooling... edited

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024

Maybe a assembly namespace level visibility would work,

The CLR doesn't offer that form of accessibility either. At best the compiler could enforce it internally but the member would still be just internal. Possibly a minor detail. There isn't a precedent of the C# compiler simulating an accessibility modifier that isn't offered by the CLR.

from csharplang.

benaadams avatar benaadams commented on July 17, 2024

An example use-case is Dictionary.Enumerator.ctor and probably most strongly typed enumerators.

The constructor is internal but its only meant to be used by Dictionary not the rest of the assembly

from csharplang.

alrz avatar alrz commented on July 17, 2024

@benaadams In that case the type itself could be defined as private.

from csharplang.

benaadams avatar benaadams commented on July 17, 2024

@alrz but then you can pass it back in a public function like public Enumerator GetEnumerator()

from csharplang.

alrz avatar alrz commented on July 17, 2024

@benaadams I see. This could use the IEnumerator interface but to avoid boxing it didn't.

EDIT: However, you can't prevent calling default ctor in a value type anyways.

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024

Enforcing that an internal constructor is only called in specific scenarios (e.g. within a parent or specific type) can easily be accomplished through a custom analyzer. I don't think it's really necessary to modify the language in order to support pseudo-accessibility modifiers.

from csharplang.

Thaina avatar Thaina commented on July 17, 2024

I would like to support this feature. And would like it to use only namespace keyword instead of namespace internal

The usefulness of this is just like friend in C++

And I think it should not need CLR support. Just compile time error

from csharplang.

ChristopherHaws avatar ChristopherHaws commented on July 17, 2024

I think many of the scenarios can be achieved with the new file-local types in C# 11, but I too really wish this were a feature! We now have assembly scoped types and file scoped types, now we just need namespace scoped types! :)

File scoped types dont work if you want to have the class be public but just the constructor be file/namespace scoped.

from csharplang.

czmirek avatar czmirek commented on July 17, 2024

For me the use case of internal namespace modifier allows for gradual separation of code into separate projects or NuGets.

Let's say I have some 100 services that all have the same structure: few public interfaces and models, IOC registration and the rest is completely internal to the service. In the end these services should really become NuGets but that requires:

  • maintaining our private NuGet repository
  • maintaining the project in a different GIT repository
  • CI/CD pipelines

This requires too much time and work.

So the other option is to simply keep the services as different projects in the solution - which is what I'm doing now. 100 projects is not too many but the performance hit in Visual Studio is definitely there when opening or closing the solution.

But with internal namespaces?

I could have everything in a single project from the start, no need to suffer the performance hit with 100 projects. I can just have 100 folders in a single project. The "hidden internals" of my services would just stay hidden in its internal namespace.

//public part of the service
namespace SomeServiceNamespace
{
    public interface ISomeService
    {
        Task DoStuffAsync();
    }
}

//hidden part of the service
internal namespace SomeServiceNamespace.Internals
{
    public class ServiceImplementation : ISomeService
    {
        public async Task DoStuffAsync()
        {
             //...
        }
    }
}

When there's enough resources (meaning development time and/or money) the code from internal namespaces can be moved not to a different project but to a completely different repository and become a NuGet in our local NuGet store with its own CI/CD.

from csharplang.

DavidArno avatar DavidArno commented on July 17, 2024

@czmirek,

The "hidden internals" of my services would just stay hidden in its internal namespace.

Genuine question: what purpose does that "hidden internals" have within these services?

The reason I ask is that encapsulation to me means "stuff hidden away from the public eye". It's implementation details that I'm free to modify whenever I want without causing changes to the public API surface of my assemblies. Whether those implementation details are private or internal makes very little difference. If the thing exists in a class, I'll mark it private as that's what's available. If private didn't exist, I'd mark it internal and I'd really not care. It's all internal to the the assembly and so hidden away, it doesn't make any difference.

The only way this becomes a concern is if one steps onto the InternalsVisibleTo slippery slope. At that point internal stuff is now public too and so there's a need for a way of saying "really internal to" (which is the important part of this thread to me).

So what is the user case behind you wanting to hide some internal parts of an assembly from other parts? It all seems needlessly complicated to me.

from csharplang.

czmirek avatar czmirek commented on July 17, 2024

@DavidArno

@czmirek,

The "hidden internals" of my services would just stay hidden in its internal namespace.

Genuine question: what purpose does that "hidden internals" have within these services?

Say you want to have service interface ISomeService, it's some external dependency, whatever. You know it's gonna have at least two or three implementations. This is pretty normal in .NET MAUI when you are building something for multiple platforms. But also on backend when you mock your services for regression testing, etc.

Now you want to follow this convention for namespaces:

MyCompany.[MyProject].MyService.Interfaces ...or Abstract or Models, basically a library defining the contracts without implementation

Then

MyCompany.[MyProject].MyService.SomeImplementation
MyCompany.[MyProject].MyService.OthetImplementation

So what, right? This is what Microsoft normally does.

My options are:

  • put everything in the runnable project. Yeah, that works of course.

The "ugly" thing is that SomeImplementation can access OtherImplementation and vice versa.

Of course you can use private classes but for that to work everything from a given implementation must be inside a private class of some other wrapper class which is also very ugly.

  • so you create MyCompany.[MyProject].MyService project and put everything in there, including all implementations. That works too of course.

The problem persists. SomeImplementation can access OtherImplementation and vice versa. And now you also have additional csproj in your solution.

  • or you create NuGets like everyone does

This is ideal solution but as I said in the post above, this requires too much work to set up.

With internal namespaces I could have nicer codebase with compiler checking that some implementations don't affect each other in any way.

Since it's just a matter of ugly/nice code it's probably not justified enough to be implemented...but I thought that about required properties as well :)

from csharplang.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.