Delegates in practical scenario: within class scope Vs within namespace scope - c#

What are the advantages-disadvantages of declaring a Delegate type within a class scope over declaring it directly within the namespace scope? I mean the following two -
namespace MyNamespace
{
public delegate string NamespaceScopeDelegate(int x, int y);
public class ClassX
{
//class members
}
}
and,
namespace YourNamespace
{
public class ClassA
{
public delegate string ClassScopeDelegate(int x, int y);
//...
//other class members
}
}
What sort of practical scenario would make me use the later one? I mean where exactly is it appropriate?
EDIT :
For the first case whenever I need to instantiate the delegate type, I can do that as -
var delegateInstance = new NamespaceScopeDelegate(MethodToPoint);
But for the second case, I must use the enclosing type name as -
var delegateInstance = new ClassA.ClassScopeDelegate(MethodToPoint);
Why would I want to do that? Does the second case provide any sort of encapsulation that I'm no aware of yet? Is there any special scenario that requires this sort of accessibility?

In your current examples, the only difference is that the second one doesn't clutter your namespace, you need to reference the class it is declared in first. You can use it to make clear that the delegate has a close relationship with the class and it is mostly used by it alone.
The following is also possible (either internal or private):
namespace YourNamespace
{
public class ClassA
{
internal/private delegate string ClassScopeDelegate(int x, int y);
//...
//other class members
}
}
By making it internal, only the same assembly can access it, and it doesn't clutter your namespace, by making it private, only the class itself may access the delegate declaration.

You need to understand that namespaces are just a nifty naming tool for your classes/delegates.
Take this code, for example:
namespace YourNamespace
{
public class ClassA
{
}
}
It produces a class with the name YourNamespace.ClassA. There isn't any actual namespace - just a class with dotted name notation.
The same is true for delegates defined inside classes.
What matters is how you wish to organize your code.
Simple as that.

What sort of practical scenario would make me use the later one?
For delegates, probably none.
From Nested Types as already mentioned in a comment:
Do not use nested types if the type is likely to be referenced outside of the declaring type. Declaration of variables and object instantiation for nested types should not be required in common scenarios. For example, an event-handler delegate that handles an event defined on a class should not be nested in the class.

Related

Why member access modifier does matter for nameof()?

I'm a little bit confused with nameof() operator. So for example I can't use class's private fields in nameof() in another class, but I can use public non static fields using non static property, so I don't need instantiated object.
Is it consistently? Why member access modifier does matter for nameof()?
class A
{
private int X;
public int Y;
public A()
{
var x = nameof(A.X);//OK
var y = nameof(A.Y);//OK
}
}
class B
{
public B()
{
var x = nameof(A.X);//Compilation error
var y = nameof(A.Y);//OK
}
}
The purpose of access modifiers like private is to hide the implementation details. They are saying "Nope, you don't need to know this. This is implementation detail". That's why nameof is not allowed to access private properties. Whatever class you are in, that class should not know about the implementation details of some other class.
Static vs non-static is different. Its purpose is not to hide something that you don't need to know about. Its purpose is just to distinguish between members that belongs to instances of the class and members that belongs to the class itself. All you want here is just the name of that member, which requires no instances to be created, so why disallow you? Note that the member is accessible i.e. it's not something you shouldn't know about.
Field X in class A is private. door is locked, you cant access it no matter what you do.
This is not a nameof problem, its Access Modifier problem
Access Modifiers (C# Programming Guide)
All types and type members have an accessibility level, which controls
whether they can be used from other code in your assembly or other
assemblies. You can use the following access modifiers to specify the
accessibility of a type or member when you declare it:
and
public The type or member can be accessed by any other code in the same assembly or another assembly that references it.
private
The type or member can be accessed only by code in the same class or struct.
protected The type or member can be accessed only by code in the same class, or in a class that is derived from that class. internal
The type or member can be accessed by any code in the same assembly,
but not from another assembly.
protected internal The type or member can be accessed by any code in the assembly in which it is declared, or from within a derived class
in another assembly.
private protected The type or member can be accessed only within its declaring assembly, by code in the same class or in a type that is
derived from that class.
Not a direct answer to your question, but I usually get around this but using a static helper class:
class A
{
public static class Properties
{
public const string X = nameof(A.X);
}
private string X { get; }
}
Then using
A.Properties.X
It's a little bit more verbose, but still enables refactoring tools to work effectively.

Avoid using class name for generic static classes with unqualified generic types

Say I have a static class that defines a bunch of delegates that looks like the following:
namespace MyNamespace {
public static class Delegates<T> {
public delegate T Create(T input);
public delegate T Update(T input);
public delegate T Get(Guid id);
public delegate bool Delete(Guid id);
}
}
I then have a generic class that uses those delegates, where the generic type of the dependent class is the same as the generic type on the static class.
namespace MyNamespace {
public class MyClass<T> {
public void MyMethod(Delegates<T>.Create create) {
T foo = GenerateSomeT();
create(foo);
}
}
}
I'd love to get rid of the Delegates<T>. prefix in the MyMethod implementation because I believe it improves the code's readability. Normally I've removed the static class as a prefix via the "using static" directive from C# 6. But in this situation T is not a "fully-qualified-type-name", so I don't see a way to accomplish this. I'd love to do something like the following example, but this does not work as one would expect. The reason is because T is still undefined outside of the MyClass's scope.
using static MyNamespace.Delegates<T>;
namespace MyNamespace {
public class MyClass<T> {
public void MyMethod(Create create) {
T foo = GenerateSomeT();
create(foo);
}
}
}
The compiler does not allow me to move the "using static" directive inside of the class either.
Is is possible to employ the using static directive, or some other trick, to avoid explicitly stating a generic static class's with an unqualified generic type every time a consumer wants to use one of its properties or methods?
Can’t you simply make Delegates non generic, and make the delegates themselves generic?
public static class Delegates
{
public delegate T Create<T> Create(T input);
//etc
}
And now T in MyClass<T> should be in scope:
using static Delegates;
public class MyClass<T>
{
public void MyMethod(Create<T> create)
{
//...
}
}
But once you get to this point, you'd have to realize that this is pointless. Delegates are types themselves, they don't need to be contained inside a class, so you can simply do:
public delegate T Create<T>(T t);
public class MyClass<T>
{
public void MyMethod(Create<T> create)
{
//...
}
}
No static using directives needed. This is how all inbuilt framework delegates are defined: Func<>, Action<>, etc.
Short answer is no, we cannot do that.
you cannot write a using statement with a generic type parameter whose type is not yet resolvable to a concrete type or interface type.
From Microsoft Docs:
A generic class, such as GenericList listed in Introduction to Generics, cannot be used as-is because it is not really a type; it is more like a blueprint for a type. To use GenericList, client code must declare and instantiate a constructed type by specifying a type argument inside the angle brackets. The type argument for this particular class can be any type recognized by the compiler.
All the T parameters needs to be get resolved via calling code that are using that generic type and in case of using statement we cannot specify any way that which type should be replaced instead of generic T parameter.
You can do something like: using static MyNamespace.Delegates<SomeType> but not what you are trying to do. You need to stick with what you tried in first approach i think.
EDIT:
After doing a quick search i found a similar question here.

How does c# handle nested (generic) types?

I'm trying to understand how C# views types in the face of nesting.
More specifically I'm trying to understand why some types are not considered assignment compatible or even castable, when there "kind of" only exist one definition of the nested class. Does the compiler / CLR actually generate different types for these, or what rules are at play exactly...
Example code:
public class Foo<T>
{
protected class Private2 : Private1<Foo<T>>
{ }
protected class Private1<T2> where T2 : Foo<T>
{
public sealed class Nested
{
public void Test(T2 foo)
{
foo.Method2(this); //Nope!
var nes = (Private2.Nested)this; //Nope!
}
}
}
public void Method1()
{
var nested = new Private2.Nested();
nested.Test(this);
}
private void Method2(Private2.Nested nested)
{
// something code...
}
}
So even though the nested instance is created as a Private2.Nested it can not be casted to that type. And... well... how do the different Nested types relate to each other given that Nested is in fact sealed? (They can't be inheriting from each other right? But on the other hand their implementation should be 100% identical... am I wrong?)
Primary question: What exactly is the compiler doing when it "compiles" this nested class?? How many unique types (excluding valuetype-related) are actually generated, and if it is all the "same" type, is the restriction artificial (as in wouldn't an unsafe cast actually work)? (What I'm saying is that the IL for all these types comes from the same code definition - so at some level the compiler must know. Are instances of these types not bit-for-bit identical apart from their type-names?)
Secondary question: not what I'm really asking here, mostly for brevity / context: is there some simple change that would make the above work? Am I missing something obvious?
The type Foo<T> must never be directly referenced inside Private1<T2> - only use of T2 is allowed. Foo<T> is just my example stand in for nasty generic classes with 10~20 generic types. It's all just a "workaround" for not being able to alias a generic class with its types:
public class Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair>
{
//If only this was real...
using BarT = Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair>;
public void Method1(BarT bar) { ... } //so good!!
//goodbye readability... see you never...
public void Method2(Bar<GoodName, OtherName, Readability, NopeMr, DontThinkSo, Suffering, Dispair> whatIsThisVariable) { ... }
}
Purpose: To avoid types of fields and method-parameters that are several screens wide and utterly unreadable! >:(
...As a side note I really wished this could be used as a type inside classes and interfaces, as in Private2 : Private1<this>. Well ok, that wouldn't work because it collides with extension syntax on methods, but something similar, perhaps <this>, <super>, <base> used like Method(<this> arg) or Private2 : Private1<<super>> ... kind of weird maybe.
Consider this types:
public class Base {
public static int Value;
public class Nested { }
}
public class Derived:Base { }
What is Derived.Value and Derived.Nested. Actually, when you refer to inherited static members (nested class considered to be static member) thru derived class, you just reference base class members, so this have exactly same meaning as Base.Value and Base.Nested at compile time. There are no separate static field Derived.Value or separate class Derived.Nested.
public static void Test() {
Derived.Value=10;
Console.WriteLine(Base.Value);
Base.Value=20;
Console.WriteLine(Derived.Value);
Base.Nested bn=new Derived.Nested();
Derived.Nested dn=new Base.Nested();
Console.WriteLine(typeof(Base.Nested).FullName);
Console.WriteLine(typeof(Derived.Nested).FullName);
Console.WriteLine(typeof(Base.Nested)==typeof(Derived.Nested));
}
Original answer:
Foo<A>.Private1<B>.Nested and Foo<C>.Private1<D>.Nested considered to be different types if A!=C or B!=D. They can share same implementation internally, but for assignment compatibility they are different. Foo<T>.Private2.Nested is just alias to Foo<T>.Private1<Foo<T>>.Nested. And even if class Bar:Foo<A>{}, classes Foo<A>.Private1<Foo<A>>.Nested and Foo<A>.Private1<Bar>.Nested still considered to be different types. So Foo<T>.Private1<T2>.Nested can not be converted to Foo<T>.Private1<Foo<T>>.Nested as T2 is not necessary Foo<T>.
You're not thinking with portals. Your inner classes are already generalized on T.
public class Foo<T>
{
private class Private2 : Private1
{ }
private class Private1
{
public sealed class Nested
{
public void Test( Foo<T> foo )
{
foo.Method2( this ); //Yup
var nes = (Private2.Nested)this; //Yup
}
}
}
public void Method1()
{
var nested = new Private2.Nested();
nested.Test( this );
}
private void Method2( Private2.Nested nested )
{
// something code...
}
}
Partial answer to the primary question:
It was bugging me that you can make the code compile by changing Method2 to accept an object and cast it at runtime, because the nested instance is of the correct type (it's instantiated inside Method1). That would seem to work - as long as Foo is sealed - but as soon as someone else can subclass Private1 it is no longer guaranteed to work. (And thus not a solution.) However testing this approach reveals:
Private2.Nested is only a construct of syntax rules - using GetType() on the resulting variable says Private1.Nested and there is no Private2.Nested type.
I think the irksome feeling I was getting from this (and why I concidered sealed to be related) was some kind of confusion on my part when it came to distinguishing between subtype and inheritance. Because the outer classes are inheriting (Private1 and Private2) it feels like inheritance, and thus it feels like it should somehow be castable. But if I understand this correctly they are merely of the same subtype:
There need not be and is in fact no inheritance relation one way or the other (as the sealed clearly hints) because "the inheritance hierarchy is distinct from from the subtype hierarchy", and thus a downright conversion would be needed (since casts are bound to the inheritance hierarchy).

Selecting object from different namespace at run timein c#?

Is it possible to select a namespace for classes at runtime. We have two copies of auto generated objects in different namespaces. Here is an example:
Namespace1
ClassA
ClassB
Namaspace2
ClassA
ClassB
Formerly, the code is simple like below
using Namespace1
...
ClassA.AMethod()
However, we need to select namespace at runtime using a condition variable. Is there a way to define a GetNamespace() method and use it like below or is there any other way you recommend?
GetNamespace().ClassA.AMethod()
Cheers,
Burak
As far as I know, there is no way to dynamically select the namespace, but I think you're in the perfect situation to use a factory. To do so, all your A classes must derive from an abstract one:
namespace Common {
public abstract class AbsA
{
//...
}
public class MyFactory
{
public MyFactory()
{
//...
}
public AbsA getA()
{
AbsA a;
if (condition)
a = new Namespace1.A();
else
a = new Namespace2.A();
return a;
}
}
}
Then you ask your factory for object creation:
MyFactory factory = new MyFactory();
labelMessage.Text = factory.getA().Something;
This complicates your structure a bit, but also makes it more coherent.
Two types from different namespaces are entirely different types as far as the CLR is concerned. Basically you'd need to consider the same solutions as you would for picking between any other arbitrary types... e.g. making both classes implement the same interface, and instead of GetNamespace() returning a namespace, it would have to return the object itself.
Given that you can:
var type = Type.GetType("Namespace1.ClassA");
object instance = Activator.CreateInstance(type);
If you then want to invoke methods on that instance, you need to either cast it to a common interface, or get a MethodInfo instance to invoke. If you control the generation of the classes, I would recommend the interface approach:
public interface IClassA
{
void AMethod();
}
namespace Namespace1
{
public class ClassA : IClassA
{ /* Stuff... */ }
}
That way, you need only:
var type = Type.GetType("Namespace1.ClassA");
IClassA instance = (IClassA)Activator.CreateInstance(type);
instance.AMethod();
Most autogenerated classes using tools such as Linq-to-Sql, Entity Framework, and even WCF proxies are created as partial, which means you can create an additional file, e.g. ClassA.partial.cs and add more to your class declarations without modifying the auto-generated class:
partial class ClassA : IClassA { }

Namespace-only class visibility in C#/.NET?

In C#, can you make a class visible only within its own namespace without living in a different assembly? This seems useful for typical helper classes that shouldn't be used elsewhere.
(i.e. what Java calls package-private classes)
You can make the classes internal but this only prevents anyone outside of the assembly from using the class. But you still have to make a separate assembly for each namespace that you want to do this with. I'm assuming that is why you wouldn't want to do it.
Getting the C# Compiler to Enforce Namespace Visibility
There is an article here (Namespace visibility in C#) that shows a method of using partial classes as a form of "fake namespace" that you might find helpful.
The author points out that this doesn't work perfectly and he discusses the shortcomings. The main problem is that C# designers designed C# not to work this way. This deviates heavily from expected coding practices in C#/.NET, which is one of the .NET Frameworks greatest advantages.
It's a neat trick… now don't do it.
I don't think that what you want is possible.
internal is assembly (strictly speaking module) privacy. It has no effect on namespace visibility.
The only way to achieve privacy of a class from other classes within the same assembly is for a class to be an inner class.
At this point if the class is private it is invisible to anything not in that class or the outer class itself.
If protected it is visible to everyone that could see it when private but is also visible to sub classes of the outer class.
public class Outer
{
private class Hidden { public Hidden() {} }
protected class Shady { public Shady() {} }
public class Promiscuous { public Promiscuous() {} }
}
public class Sub : Outer
{
public Sub():base()
{
var h = new Hidden(); // illegal, will not compile
var s = new Shady(); // legal
var p = new Promiscuous(); // legal
}
}
public class Outsider
{
public Outsider()
{
var h = new Outer.Hidden(); // illegal, will not compile
var s = new Outer.Shady() // illegal, will not compile
var p = new Outer.Promiscuous(); // legal
}
}
In essence the only way to achieve what you desire is to use the outer class as a form of namespace and restrict within that class.
No, it is possible. You can use internal class in another assembly.
For example I have a internal string extension class that located in SharMillSoft.Core assembly, if I want use it in another assembly that name is SharpMilSoft.Extension, I must use assembly attribute like as below:
using System;
using System.Linq;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("SharpMilSoft.Extensions")]
namespace SharpMilSoft.Core.Extensions.Strings.Public
{
internal static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return string.IsNullOrEmpty(data);
}
}
}
And I use this class in SharpMilSoft.Extension assembly like as below:
namespace SharpMilSoft.Extensions.Strings
{
public static class SharpStringExtensions
{
public static bool IsNullOrEmpty(this string data)
{
return Core.Extensions.Strings.Public.SharpStringExtensions.IsNullOrEmpty(data);
}
}
}
Note: Then SharpMilSoft.Extensions assembly will be friend assembly for SharpMilSoft.Core assembly
For more details about friend assembly, you can visit this link : Friend assemblies
If you have a single assembly you can define as many namespaces in that assembly as you want but no matter what modifier you apply in the IDE you will always be able to see the classes in other namespaces.
Not sure if it is directly possible, but a few good ways to fake it would be:
1) Have the classes that need this sort of stuff inherit from a single class which has the helper class as an internal class.
2) Use extension methods and then only reference the extension methods within the namespace.

Categories

Resources