Access modifiers on properties; why doesn't the following work? - c#

I've run into a compiler error that doesn't quite make sense to me. I have an internal property and I want to restrict its set block such that it is only available through inheritance. I thought this would work:
internal bool MyProperty {
get { return someValue; }
protected internal set { someValue = value; }
}
But the compiler says that the access modifier on the set block needs to be more restrictive than internal - am I missing something, or is protected internal not more restrictive than internal?

protected internal is less restrictive; it is protected or internal (not and) - which therefore additionally allows subclasses from other assemblies to access it. You would need to invert:
protected internal bool MyProperty {
get { return someValue; }
internal set { someValue = value; }
}
This will allow code in your assembly, plus subclasses from other assemblies, get it (read) - but only code in your assembly can set it (write).

From the documentation on Access Modifiers in C#:
The protected internal accessibility
level means protected OR internal, not
protected AND internal. In other
words, a protected internal member can
be accessed from any class in the same
assembly, including derived classes.
To limit accessibility to only derived
classes in the same assembly, declare
the class itself internal, and declare
its members as protected.
To achieve the desired effect, you instead need to swap the access modifiers, like so:
protected internal bool MyProperty
{
get { return someValue; }
internal set { someValue = value; }
}

No, it's the union of the two, not the intersection; hence protected internal is less restrictive than both of those individually. The intersection isn't a feature of C#; the CLR does support "Family AND Assembly", but C# only supports "Family OR Assembly".

Here, protected internal is less restrictive that internal.
protected internal - public for current assembly and any type that inherits this type in other assemblies.
internal - public for this assembly and private for other assemblies

Related

private members in interface

is this possible to create a private members in interface in .NET? I heard that it is possible now but I my IDE is rejecting it:
public interface IAnimal
{
void SetDefaultName(string name)
{
ChangeName(name);
}
private string defaultName = "NoName";
private void ChangeName(string name)
{
defaultName = name;
}
void Breath()
{
Console.WriteLine($"Default - I'm {defaultName}. <Breathing sounds>");
}
void Sound();
}
Yes! Now you can in C# 8.0 but it has to be a static member. Like this:
public interface IAnimal
{
static void SetDefaultName(string name)
{
ChangeName(name);
}
private static string defaultName = "NoName";
private static void ChangeName(string name)
{
defaultName = name;
}
void Breath()
{
Console.WriteLine($"Default - I'm {defaultName}. <Breathing sounds>");
}
void Sound();
}
But you need to keep in mind that static fields will be shared across the application. Changing the defaultName will result in changing it in every place where you are using IAnimal
private methods used to be prohibited in interfaces because interfaces are supposed to be contracts. They are a guarantee that "this class has the following methods and properties". Why would it be useful to guarantee that a class has a private method? It isn't useful, because no one else can call it!
In C# 8, this changed. You can now specify private interface default methods. Note that it has to be a default method, not the ones that doesn't have an implementation. Here's the docs stating that fact:
The syntax for an interface is relaxed to permit modifiers on its members. The following are permitted: private, protected, internal, public, virtual, abstract, sealed, static, extern, and partial.
...
It is an error for a private or sealed function member of an interface to have no body.
Here is a quote from the docs explaining why this is allowed:
Static and private methods permit useful refactoring and organization of code used to implement the interface's public API.
The actual question should be : should i do (or be able to do) it or not ?
The whole idea of the interface thing is to provide abstraction .
private members usually are implementation details that the consumer of your code shouldn't care about or know they exists so they don't belong to your abstract layer (interface)
the interface is the facade that the consumer will interact with ur service/component thorough , it should contain only the methods that the consumer will call , this is why originally interfaces should have only public modifiers
not to mention that putting such members in the interface will force every implementation of it to implement these members even if they don't need it
from my opinion the only reason C# changed interfaces and made them allow implementation is to make up for the language lack of support for multiple class inheritance , but that does mean that you should miss use ur interfaces like that
Yes, with C# 8.0, you can have public, private and protected members.
For example, following works:
public interface ITest
{
private SomeEnum EnumTy { get => SomeEnum.Value1; }
}
If a class implements an interface and tries to access the variable, they will get an error.
public class TestImpl : ITest
{
ITest.EnumTy = SomeEnum.Value2; // gives an error
}
The members can also be protected. As a suggestion, going forward its good to have public before methods to indicate more readability (even though public is default).
A good article is here:
https://jeremybytes.blogspot.com/2019/11/c-8-interfaces-public-private-and.html

FxCop CA1047 - Abstract and accessibility level

I have this code (sample to reproduce):
public class ObjectBase<T>
{
}
public abstract class ExportBase
{
public void ExportData<T>(string path, T data, string filename)
where T : ObjectBase<T>
{
// Several verifications on data.
// Example:
if (data != null)
{
this.InnerExport(this.GetFileName<T>(path, filename), data);
}
}
protected abstract void InnerExport<T>(string path, T data)
where T : ObjectBase<T>;
public string GetFileName<T>(string path, string filename)
{
// Code.
return "TEST";
}
}
internal sealed class XmlExport : ExportBase
{
protected override void InnerExport<T>(string path, T data)
{
// Code.
}
}
I don't want XmlExport visible (internal in my class library) nor inherits (sealed).
With FxCop 10.0, I've got an CA1047:DoNotDeclareProtectedMembersInSealedTypes:
Name: (FxCopCmd)
Do not declare protected members in sealed types.
Description: (FxCopCmd)
Sealed types cannot be extended, and protected members
are only useful if you can extend the declaring type. Sealed types
should not declare protected members.
How to fix: (FxCopCmd)
Make member 'XmlExport.InnerExport(string, T)' private,
public, or internal (Friend in Visual Basic).
Info: (FxCop)
Sealed types cannot be extended, and protected members
are only useful if you can extend the declaring type.
Sealed types should not declare protected members.
But I can't change protected to private: virtual or abstract members can't be private.
Nor public (does not make sense, here).
I know I can use a SuppressMessage, but I'm wondering if there is a better way (including a modification of the classes).
Thanks.
This appears to be due to a bug in the rule, triggered by the generic constraint ("where T : ObjectBase") on the base InnerExport method declaration. You should suppress the violation as a false positive. If you're feeling particularly keen, you could also report the bug at https://connect.microsoft.com/visualstudio/.
You could change protected to internal if you only will use this in the library. But you would also have to change it to internal in XmlExport when you override.

How do I look up the internal properties of a C# class? protected? protected internal?

If I have a C# class MyClass as below:
using System.Diagnostics;
namespace ConsoleApplication1
{
class MyClass
{
public int pPublic {get;set;}
private int pPrivate {get;set;}
internal int pInternal {get;set;}
}
class Program
{
static void Main(string[] args)
{
Debug.Assert(typeof(MyClass).GetProperties(
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance).Length == 1);
Debug.Assert(typeof(MyClass).GetProperties(
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance).Length == 2);
// internal?
// protected?
// protected internal?
}
}
}
The code above compiles are runs without any assertion failures. NonPublic returns the Internal and Private properties. There does not appear to be flags for the other accessibility types on BindingFlags.
How do I get a list/array of only the properties that are internal? On a related note, but not necessary for my application, what about protected, or protected internal?
When you get the property infos with BindingFlags.NonPublic, you find the getter or setter by using GetGetMethod(true) and GetSetMethod(true), respectively. You can then check the following properties (of the method info) to get the exact access level:
propertyInfo.GetGetMethod(true).IsPrivate means private
propertyInfo.GetGetMethod(true).IsFamily means protected
propertyInfo.GetGetMethod(true).IsAssembly means internal
propertyInfo.GetGetMethod(true).IsFamilyOrAssembly means protected internal
propertyInfo.GetGetMethod(true).IsFamilyAndAssembly means private protected
and similarly for GetSetMethod(true) of course.
Remember that it is legal to have one of the accessors (getter or setter) more restricted than the other one. If there is just one accessor, its accessibility is the accessibility of the entire property. If both accessors are there, the most accessible one gives you the accessibility of the whole property.
Use propertyInfo.CanRead to see if it's OK to call propertyInfo.GetGetMethod, and use propertyInfo.CanWrite to see if it's OK to call propertyInfo.GetSetMethod. The GetGetMethod and GetSetMethod methods return null if the accessor does not exist (or if it is non-public and you asked for a public one).
See this article on MSDN.
Relevant quote:
The C# keywords protected and internal have no meaning in IL and are
not used in the reflection APIs. The corresponding terms in IL are
Family and Assembly. To identify an internal method using reflection,
use the IsAssembly property. To identify a protected internal method,
use the IsFamilyOrAssembly.
GetProperties with System.Reflection.BindingFlags.NonPublic flag returns all of them: private, internal, protected and protected internal.

Am I trying to Implement Multiple Inheritance. How can I do this

I have created a class say A which has some functions defined as protected.
Now Class B inherits A and class C inherits B. Class A has private default constructor and protected parameterized constructor.
I want Class B to be able to access all the protected functions defined in Class A but class C can have access on some of the functions only not all the functions and class C is inheriting class B.
How can I restrict access to some of the functions of Class A from Class C ?
EDIT:
namespace Db
{
public class A
{
private A(){}
protected A(string con){assign this value}
protected DataTable getTable(){return Table;}
protected Sqlparameters setParameters(){return parameter;}
}
}
namespace Data
{
public class B:A
{
protected B():base("constring"){}
protected DataTable output(){return getTable();}
protected sqlparameter values(param IDataParameter[] parameter){}
}
}
namespace Bsns
{
public class C:B
{
protected C():base(){}
protected DataTable show()
{return values(setparameter());}
}
}
EDIT
I think what I am trying to do here is Multiple inheritance.
Please check.
class A
{
//suppose 10 functions are declared
}
class B:A
{
//5 functions declared which are using A's function in internal body
}
class C:B
{
//using all functions of B but require only 4 functions of A to be accessible by C.
}
You need to have classes A and B in the same assembly and class C in another assembly. You can mark the member you want to restrict access to by derived classes as protected internal. This makes the member, well, protected and internal. As far as limiting class C's access to the member it will suffice to mark it internal. Since this will make it it public within the first assembly, you might want to add protected to enforce encapsulation.
Turns out marking a member protected internal doesn't make it private to classes outside of the assembly. Seems that for all intents and purposes protected internal is the same as protected. Unfortunately the only way I can see achieving this would be to mark it internal and put up with the member being public to the defining assembly.
Even C# programming guide on MSDN gets it wrong:
By combining the protected and
internal keywords, a class member can
be marked protected internal — only
derived types or types within the same
assembly can access that member.
Phil Haack explains:
protected internal means protected OR
internal
It’s very clear when you think of the
keywords as the union of accessibility
rather than the intersection. Thus
protected interna means the method is
accessible by anything that can access
the protected method UNION with
anything that can access the internal
method.
Here is the updated code:
class A {
protected void Test3(){} //available to subclasses of A in any assembly
protected internal void Test() { } //Same as protected :(
public void Test2(){}//available to everyone
internal void Test4(){} //available to any class in A's assembly
}
class B : A {
void TestA() {
Test(); //OK
}
}
//Different assembly
class C : B {
void TestA() {
Test4(); //error CS0103: The name 'Test4' does not exist in the current context
}
}
It looks like you should probably using Composition not Inheritance.
Class A implements calc() and allow().
Class B has a private A but isn't derived from A
Class C derives from B and has no access to the private A object in class B.
I'd suggest that you rethink your design. Maybe there is a simpler way. What if C uses an instance of B instead of deriving from it (composition) ? That way C can use B's public methods but not get access to the protected ones.
Class A should not care about the level/depth of a descendant. If something is marked protected, it should be protected for both B and C (regardless of the depth of the inheritance chain).
B may choose to delimit its descendants by tightening the constraints (but this is rare).
If you can tell me more about your context - the problem you are trying to solve.. I can give you a more detailed/useful answer.
As others have said, you probably want to use composition instead of inheritance.
class A {
protected void Foo() { … }
protected int Bar() { … }
}
class B {
private A a;
public B() {
this.a = new A();
}
protected int Bar() {
return a.Bar();
}
}
class C : B { … }
Looking at your example, though, I would question whether C should inherit from B, or whether it should really just hold a reference to an object of type B.
Personally, I wouldn't go putting classes in different assemblies just for the purpose of restricting access if the class doesn't otherwise logically belong in a different assembly. There are other ways to handle it.

Why does FxCop treat protected as public?

Why does FxCop treat protected members as if they are public throwing DoNotDeclareVisibleInstanceFields error? I'm pretty sure protected members is a valid code design.
It's telling you not to declare fields which are visible outside the class, i.e. not private. In this case it is correctly recognising the protected modifier as exposing the members outside the class, albeit only to derived types.
I'm not sure if that's what you meant, but in general protected members are part of a class' interface.
You don't want public member variables because they make your implementation inflexible. Protected member variables do the same since classes that inherit from yours will depend on them, thus making your implementation inflexible.
Asaf
It looks like the error you're getting is flagging your externally visible instance fields. The recommended practice here is to make this field private and expose it through an externally visible property (with a public or protected access modifier).
The MSDN page on the error gives a good example:
using System;
namespace DesignLibrary
{
public class BadPublicInstanceFields
{
// Violates rule DoNotDeclareVisibleInstanceFields.
public int instanceData = 32;
}
public class GoodPublicInstanceFields
{
private int instanceData = 32;
public int InstanceData
{
get { return instanceData; }
set { instanceData = value ; }
}
}
}

Categories

Resources