• No results found

Access Modifiers

In document Basic c# (Page 125-134)

Compiler Error

a.cs(7,6): error CS0030: Cannot convert type 'xxx' to 'yyy' a.cs(8,6): error CS0030: Cannot convert type 'yyy' to 'xxx'

Unfortunately casting works only if one of the two classes is derived from the other. You cannot cast any two objects to each other.

a.cs class zzz {

public static void Main() {

int i = 10;

char j = 'A';

i = j;

j = i;

} }

Compiler Error

a.cs(8,5): error CS0029: Cannot implicitly convert type 'int' to 'char' We are allowed to convert a char into a int as i = j but not the other way round as j = i.

8

Modifiers

Access Modifiers

Public, Private, Protected and Internal

Whenever a class is created by us we want to have the ability to decide who can access certain members of the class. In other words, we would like to restrict access to the members of the class. The basic rule is that members of a class can freely access each other. There is no way one can prevent a function of a particular class from executing another function in the same class. By default though, the same class is allowed complete access but no one else is granted access to the members of the class. The default access modifier is private.

a.cs class zzz {

public static void Main() {

yyy.pqr();

} }

class yyy

{

static void abc() {

System.Console.WriteLine(“yyy abc”);

}

public static void pqr() {

System.Console.WriteLine(“yyy pqr”);

abc();

} } Output yyy pqr yyy abc

Pqr is public and hence anyone is allowed to execute it. abc has no access modifier which makes it private, which is anyway the default. The private modifier has no effect on members of the same class and hence pqr is allowed to call abc. This concept is called member access.

a.cs class zzz {

public static void Main() {

yyy.abc();

} }

class yyy {

static void abc() {

System.Console.WriteLine(“yyy abc”);

}

public static void pqr() {

System.Console.WriteLine(“yyy pqr”);

abc(); } } Compiler Error

a.cs(5,1): error CS0122: ‘yyy.abc()’ is inaccessible due to its protection level abc is private an no one but members of yyy can access it.

a.cs class zzz {

public static void Main() {

yyy.abc();

} }

class yyy {

protected static void abc() {

System.Console.WriteLine(“yyy abc”);

}

public static void pqr() {

System.Console.WriteLine(“yyy pqr”);

abc();

} }

Compiler Error

a.cs(5,1): error CS0122: ‘yyy.abc()’ is inaccessible due to its protection level

We have now introduced one more access modifier, protected, which also does not let you access a class from outside. However pqr is allowed to access abc as access modifiers do not effect the same class as mentioned earlier.

a.cs class zzz {

public static void Main() {

xxx.aaa();

} }

class yyy {

static void abc() {

System.Console.WriteLine(“yyy abc”);

}

public static void pqr() {

System.Console.WriteLine(“yyy pqr”);

}

protected static void xyz() {

System.Console.WriteLine(“yyy xyz”);

} }

class xxx : yyy {

public static void aaa() {

abc();

pqr();

xyz();

} }

Compiler Error

a.cs(27,1): error CS0122: ‘yyy.abc()’ is inaccessible due to its protection level

We are now dealing with derived classes. When we flag a function with the modifier, protected, we are informing C# that only derived classes can access the function. Nobody else can. Thus in function aaa we can call xyz as it is flagged protected, but it cannot be called from anywhere else including Main.

The function abc is private and can be called only from the class yyy. Comment out abc(); in aaa and csc will show you no errors.

To sum up, we have learnt three concepts. Private means only the same class has access, public means everyone has access and protected lies in between where only derived classes have access.

All functions for example reside in a class. The accessibility of that function is decided by the class in which it resides as well as the modifiers on the function. If we are allowed access to a member, we say that the member is accessible, else inaccessible.

b.cs

internal class yyy {

}

csc /t:library b.cs

This command will produce a library b.dll with one class yyy.

a.cs class zzz {

public static void Main() {

yyy a;

} }

>csc a.cs /r:b.dll Compiler Error

a.cs(5,1): error CS0122: ‘yyy’ is inaccessible due to its protection level

We get the above error as the modifier internal means that we can only access yyy from b.dll and not from any other file or program. Never create a component and flag the class internal as no one would be able to use it. Internal means access limited to this program only.

Also writing csc a.cs b.cs would not give us any error.

a.cs

public namespace vijay {

class zzz {

public static void Main() {

} } }

Compiler Error

a.cs(1,8): error CS1518: Expected class, delegate, enum, interface, or struct

Namespaces by default can have no accessibility modifiers at all. They are public by default and we cannot add any other access modifier including public again.

a.cs

private class zzz {

}

Compiler Error

a.cs(1,1): error CS1527: Namespace elements cannot be explicitly declared as private or protected

A class can only be public or internal. It cannot be marked as protected or private. The default is internal.

b.cs class yyy {

}

csc b.cs /t:library Compiler Error

fatal error CS2022: Options ‘/out’ and ‘/target’ must appear before source file names

Mistake, done on purpose. At times we will forget to tell you that some compiler options like /t and /out must appear before the names of the source files.

>csc /t:library b.cs a.cs

class zzz {

public static void Main() {

yyy a;

} }

>csc a.cs /r:b.dll Compiler Error

a.cs(5,1): error CS0122: ‘yyy’ is inaccessible due to its protection level

Thus if we want other programs/files to access classes created by us, we must not forget that by default they are marked as internal as explained earlier.

Members of a class can have all the modifiers described above and default to private.

a.cs class zzz {

public static void Main() {

}

public private void abc() {

} }

Compiler Error

a.cs(6,8): error CS0107: More than one protection modifier

You are not allowed more than one access modifier most of the time. The exceptions, we will soon take care off. Predefined types like int, object have no accessibility restrictions. They can be used anywhere and everywhere.

b.cs class yyy {

public void abc() {

} }

csc /t:library b.cs

a.cs class zzz {

public static void Main() {

yyy a = new yyy();

a.abc();

} }

Compiler Error

a.cs(5,1): error CS0122: 'yyy' is inaccessible due to its protection level

a.cs(6,1): error CS0246: The type or namespace name 'a' could not be found (are you missing a using directive or an assembly reference?)

As the class yyy has not been specified by an access modifier, it is by default internal. Even though abc is public, the type enclosing it i.e. yyy is internal and hence no member of yyy can be accessed from outside b.cs. Thus the access modifiers of the class and the members is important.

b.cs

public class yyy {

void abc() {

} }

>csc /t:library b.cs a.cs

class zzz {

public static void Main() {

yyy a = new yyy();

a.abc();

} }

Compiler Error

a.cs(6,1): error CS0122: ‘yyy.abc()’ is inaccessible due to its protection level

Here yyy is accessible as the modifier is public but the function abc is private and hence cannot be accessed by anyone but the class.

From now on we will only display a.cs and b.cs as the command line executions of the compiler will remain the same. a.cs remains the same for this program.

b.cs

public class yyy {

internal void abc() {

} }

Compiler Error

a.cs(6,1): error CS0122: ‘yyy.abc()’ is inaccessible due to its protection level Internal means no one from outside the dll can access the function.

a.cs class zzz {

public static void Main() {

ppp a = new ppp();

a.aaa();

} } b.cs

public class yyy {

protected internal void abc() {

} }

public class xxx : yyy {

void pqr() {

abc();

} }

public class ppp {

public void aaa() {

yyy a = new yyy();

a.abc();

} }

No error occurs as protected internal means two things. It is either derived classes or classes in the same file that can access abc. Therefore derived class xxx can use it as well as class ppp.

What we are trying to get at here is that the containing type decides first the accessibility and then the member modifiers also comes in. Making the class internal and then the members public will in no way allow classes in others files access it.

a.cs class zzz {

public static void Main() {

} }

class yyy {

protected int x;

void abc( yyy a , xxx b) {

a.x = 1;

b.x = 2;

} }

class xxx : yyy {

void pqr( yyy a , xxx b)

{

a.x = 1;

b.x = 2;

} }

Compiler Error

a.cs(20,1): error CS1540: Cannot access protected member ‘yyy.x’ via a qualifier of type ‘yyy’;

the qualifier must be of type ‘xxx’ (or derived from it)

Class yyy contains a protected member x. To the same class no modifiers make sense. However as x is protected, in the derived class function pqr, we cannot access it through yyy as a.x gives us an error.

However b which looks like xxx does not give an error. To check this out, comment out the line a.x=1 in pqr(). This means that we can access the protected members not from an object of the base class, but from the derived class objects only. This is in spite of the fact that x is a member of yyy, the base class.

Even so, we still cannot access it. Also we cannot access x from the function Main.

a.cs class zzz {

public static void Main() {

} }

class yyy {

}

public class xxx : yyy {

}

Compiler Error

a.cs(10,14): error CS0060: Inconsistent accessibility: base class ‘yyy’ is less accessible than class ‘xxx’

Between internal and public, public allows greater access to its members. The class yyy is by default internal and xxx which derives from yyy is explicitly made public. We get an error as the derived class yyy has to have an access modifier which allows greater access than the base class access modifier. Here internal is more restrictive than public.

a.cs class zzz {

public static void Main() {

} }

public class yyy {

}

class xxx : yyy {

}

If we reverse the modifiers, i.e. we make yyy public and xxx the derived class internal we get no error.

The base class allows more accessibility than the derived class.

a.cs class zzz {

public static void Main()

{ } }

class yyy {

}

public class xxx {

public yyy f() {

return new yyy();

} }

Compiler Error

a.cs(12,12): error CS0050: Inconsistent accessibility: return type ‘yyy’ is less accessible than method ‘xxx.f()’

The accessibility of yyy is internal which is more restrictive than public. The accessibility of function f is public which is more than that of the type yyy. The error occurred as return values must have greater accessibility than that of the method, which is not true in this case.

a.cs class zzz {

public static void Main() {

} }

class yyy {

}

public class xxx {

public yyy a;

}

Compiler Error

a.cs(12,12): error CS0052: Inconsistent accessibility: field type ‘yyy’ is less accessible than field

‘xxx.a’

Rules are rules – they remain the same everywhere. The class yyy or data type yyy is internal. a, an object/field is public which makes it more accessible than yyy which is internal. Hence the error.

a.cs class zzz {

public static void Main() {

} }

class yyy {

}

public class xxx {

yyy a;

}

Now we get no error as a has been made private which gives it a lower accessibility than yyy which is internal. Logic is that whatever you create must be more accessible than what you create from.

In document Basic c# (Page 125-134)