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.
Related
I understand that a private protection level is meant to stop any child accessing private parent variables.
But isn't there a way to do it with accessors and mutators(get and set)? I have to have some kind of way to change a private string because that is the homework.
I have a public abstract pet class with a private string for a name. I want to create a dog and use that string name. I can't figure it out though. Since it is homework, I understand I cannot be given code or anything, but could someone point out the method to do this so I can google it? All my searches just imply that it is impossible.
Here's my code if it will help.
edit
I can't just make it protected.
public abstract class Pet
{
private string name;
private string species;
public abstract void speak();
public abstract void play();
public abstract void info();
}
Part of the child dog class...
class Dog : Pet
{
public Dog(string xname, string xspecies)
{
this.name = xname; // this is where I'm having trouble.
}
Let's make sure that you have a clear and accurate understanding; many beginners are taught subtle falsehoods.
I understand that a private protection level is meant to stop any child accessing private parent variables.
That's a correct summary of the intention of the feature. Basically you are saying that access control modifiers are for controlling access, which should not be a surprise.
However there are two subtleties that I want to point out here.
The first is that access modifiers control access to the names of things, not to the things. When you have a member named foo, the name foo may only be used to refer to that member from within the accessibility domain of that member. The "accessibility domain" is a region of program text; the accessibility domain of a private member is the text of the type which declares the member.
If you have come up with some other way to refer to a member, that mechanism is not controlled by the accessibility modifier. The only thing an accessibility modifier controls is where the name may be used in the text of the program.
Make sure that is clear in your head.
Second, you note that a private member is not accessible to a "child", by which I assume you mean a derived class. There is a situation in which a derived class can access private member by name. Given what I've said so far, you should be able to deduce what it is. Give it some thought and then read on.
I said that a private member is accessible by name only inside the text of the declaring type, so if a private member is accessible by name by a derived class, the derived class must be inside the text of the declaring type:
class Base
{
private static int x;
class Derived : Base
{
static void M() { Console.WriteLine(Base.x); }
}
}
This is legal because x is used by name inside its accessibility domain.
So, how do you do your homework problem? There are only two ways:
(1) Put Dog inside of Pet; any Dog then has access to all the private members of Pet. This is a "for advanced players only" feature of C# and almost certainly not what your instructor is looking for. But it is a really powerful technique and I use it frequently, so keep it in mind for your later career; in particular, when you learn about the "factory pattern" you can pull out of your back pocket the knowledge that putting the derived classes inside the base class is a good trick for making the factory pattern work well.
(2) Make some accessor mechanism for the private member, and make that accessor mechanism's name protected, internal, or public.
Typically you'd use a property. You make an property with a read-only accessor in C# like this:
class Base
{
private int x;
public int X { get { return x; } }
}
Or, in more modern versions of C# you can use this short form:
public int X => x;
And now code outside of Base cannot use x by name, because that is outside of the accessibility domain of Base.x. But X has an unrestricted accessibility domain, so it can be used anywhere you like.
That's a read-only accessor. To make a write accessor you add a setter:
public int X
{
get { return x; }
set { x = value; }
}
Notice that setters have a magic value name that is the value that is to be assigned to the property.
There are other ways to make accessors but this is by far the most common.
While we are looking at your code, a couple other things:
(1)
public abstract void speak();
public abstract void play();
public abstract void info();
Public methods should be PascalCasedLikeThis, not lowercase, in C#. It's just an arbitrary convention that makes it easier to read your code.
(2)
Why is info void returning? Surely it should be returning some info.
(3)
class Dog : Pet
Is your intention to further subclass Dog? Probably not, because it is not abstract. Consider marking classes not intended to be subclassed as sealed, so that you do not have to worry about designing the class for safe inheritance.
I think you're looking for the protected access modifier, which means the variable is accessible within its class and by derived class instances:
public abstract class Pet
{
protected string name;
protected string species;
public abstract void Speak();
public abstract void Play();
public abstract void Info();
}
class Dog : Pet
{
public Dog(string xname, string xspecies)
{
name = xname;
species = xspecies;
}
// Implementation of Pet here
}
I have been learning C# for two weeks now, though it is not my first either second language. I have been wondering about the static word. I know I should have researched about this word long before...but this is the first time I realized how much confusing this word is for me. For what I have read:
A static class is a class which does not need to be instanciated to be used (
Class with single method -- best approach? ). This may have some advantages and some disadvanatges regarding testing, polymorphism etc.
But the static word can be applied also to classes, fields, methods, properties, operators, events and constructors !!! ( https://msdn.microsoft.com/en-us/library/98f28cdx%28v=vs.80%29.aspx ). Example:
Property:
private static string s = "";
Method:
public static void helperMethod() {
Console.WriteLine("Whatever");
}
Does the word static have a global meaning or employed in differents parts of the code the meaning can change?
class modifier
When static is applied to a class it indicates four attributes.
Contains only static members.
Cannot be instantiated.
Is sealed.
Cannot contain Instance Constructors.
property or function modifier (and events and methods)
When applied to properties and functions, e.g.
public Thing
{
static int SharedCount { get; set; }
static string GenerateName()
{
// ...
}
}
it means that the properties and functions will be accessible via the type name, without instantiating the class. This properties and functions will not be accessible via an instance of the class. So, both
var i = Thing.SharedCount;
var s = Thing.GenerateName();
Are valid and correct statements, Where as
var i = new Thing().SharedCount;
var s = this.GenerateName();
are both incorrect.
Code in functions and properties declared with the static modifier cannot access non-static members of the class.
member variables
Member variables declared with a static modifier, e.g.
class Thing
{
private static int sharedCount = 0;
private static readonly IDictionary<string, int> ThingLookup =
new Dictionary<string, int>
{
{ "a", 1 },
{ "b", 2 }
};
}
are shared by all static functions and properties and by all instances of the class.
static constructors
When applied to constructors, e.g.
class Thing
{
static Thing()
{
\\ Do this once and first.
}
}
static means the constructor will run once per AppDomain, when the type is first accessed. There are special edge cases around this.
operators
When an operator is overloaded for a type, this is always declared as static, e.g.
public static Thing operator +(Thing left, Thing right)
{
// Something special to do with things.
}
It is not logical for this to be declared at an instance level since operators must apply to types.
These distinctions are explained here, here, here and here.
Static members are items that are deemed to be so commonplace that there is no need to create an instance of the type when invoking the member. While any class can define static members, they are most commonly found within utility classes such as System.Console, System.Math, System.Environment, or System.GC, and so on.
Also the static keyword in C# is refering to something in the class, or the class itself, that is shared amongst all instances of the class. For example, a field that is marked as static can be accessed from all instances of that class through the class name.
Quick answer: No static remains the same contextually everywhere :
From dotnetperls:
These are called with the type name. No instance is required—this makes them slightly faster. Static methods can be public or private.
Info:
Static methods use the static keyword, usually as the first keyword or the second keyword after public.
Warning:
A static method cannot access non-static class level members. It has no this pointer.
Instance:
An instance method can access those members, but must be called through an instantiated object. This adds indirection.
C# program that uses instance and static methods
using System;
class Program
{
static void MethodA()
{
Console.WriteLine("Static method");
}
void MethodB()
{
Console.WriteLine("Instance method");
}
static char MethodC()
{
Console.WriteLine("Static method");
return 'C';
}
char MethodD()
{
Console.WriteLine("Instance method");
return 'D';
}
static void Main()
{
//
// Call the two static methods on the Program type.
//
Program.MethodA();
Console.WriteLine(Program.MethodC());
//
// Create a new Program instance and call the two instance methods.
//
Program programInstance = new Program();
programInstance.MethodB();
Console.WriteLine(programInstance.MethodD());
}
}
Output
Static method
Static method
C
Instance method
Instance method
D
In C#, data members, member functions, properties and events can be declared either as static or non-static.
Only one copy of static fields and events exists, and static methods and properties can only access static fields and static events.
Static members are often used to represent data or calculations that do not change in response to object state.
Static can be used in following ways:
Static data members
Static constructor
Static Properties
Static methods
More references :
MSDN
Static
Static in c#
What is static ?
The static keyword means generally the same everywhere. When it is a modifier to a class, the class's members must also be marked static. When it is a modifier to a member, (fields, properties, methods, events etc.) the member can be accessed using the following syntax:
ClassName.memberName
Note that operators must be declared static and extension methods must be in a static class which means it also has to be static.
Word static speaks for itself. If you have something that may change for every new object of some type - it's instance member and if it stays the same for all instances - it's static member.
From MSDN :
It is useful to think of static members as belonging to classes and
instance members as belonging to objects (instances of classes).
Source : static and instance members
Static members can be accessed via class object, something like MyClass.MyMember when instance members are only accessible on instance of a class (new MyClass()).MyMember
It's obvious that compiler takes some time to create instance and only then you can access its properties. So instance members works slower than static members.
In simple words , static property is not being changed across the classes , if your static member is affecting multiple classes once you change the value of it, it will be changed in every single class that is being affected by it.
Static method has to be static if you tend to use it in a static context (static class or so..)
Static class is the one which cannot be instantiated, e.g. static class Car{} this car will always have the same properties ( colour, size...)
There are many concepts related to Static keyword.
This answer will resolve your confusion about static.
An example is worth a thousand stupid questions so:
public class OuterClass
{
public static class InnerClassEventArgs : EventArgs
{
public static int SomeInt;
}
}
and in a galaxy far far away:
public void SomeFunkyFunc()
{
OuterClass Instance1;
OuterClass Instance2;
Instance1.InnerClassEventArgs.SomeInt = 1;
Instance2.InnerClassEventArgs.SomeInt = 2;
//WHAT WOULD Instance1.InnerClassEventArgs.Someint == ?
}
Yes, I realize now that I've typed this that I've almost coded all I need to answer my own question. I'd rather not create a new project and go through the trouble if someone smarter than me knows off the top of their head.
Instance1.InnerClassEventArgs.SomeInt would equal 2. Static fields are shared across all instances of the class -- or as MSDN puts it:
The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created.
Note that your specific example won't compile -- you'll get an error message that says "Cannot access static class 'InnerClassEventArgs' in a non-static context."
You'd have to use the following code instead, which hopefully makes the behavior more understandable:
OuterClass.InnerClassEventArgs.SomeInt = 1;
OuterClass.InnerClassEventArgs.SomeInt = 2;
A static class has exactly one instance, "shared" by all its usages (in your case, all instances of OuterClass). Therefore, the state of that object will be the sum of all changes made by any usage. In this simple example, SomeInt will be 2, regardless of which OuterClass instance you used to access it again (Instance1 or Instance2).
I'm conveniently ignoring all of the following:
A static class cannot inherit from any other class. InnerClassEventArgs thus cannot inherit from EventArgs.
Instance1 and Instance2 are not initialized; this will cause its own compile-time error if you use ReSharper ("X may not be initialized before accessing").
Static members (including nested static classes) cannot be accessed based on any one instance; you would access InnerClassEventArgs in static context.
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.
namespace hi
{
class hithere
{
public int numberOne = 12;
private int numberTwo = 12;
static void yo()
{
}
}
}
Can someone tell me the difference between the variables numberOne and numberTwo in this code excerpt?
From the accessibility levels at MSDN:
public Access is not restricted.
protected Access is limited to the containing class or types derived from
the containing class.
internal Access is limited to the current assembly.
protected internal Access is limited to the current assembly or
types derived from the containing
class.
private Access is limited to the containing type.
Public variables are accessible from out side classes but private one just accessible for current class and inner classes:
public class VarClass
{
public int publicID = 10;
private int privateID = 100;
public VarClass()
{
Console.WriteLine(publicID);
Console.WriteLine(privateID);
}
public class InnerClass
{
public InnerClass()
{
VarClass c = new VarClass();
Console.WriteLine(c.privateID);
Console.WriteLine(c.publicID);
}
}
}
public class OuterClass
{
public OuterClass()
{
VarClass c = new VarClass();
Console.WriteLine(c.privateID); // Compile Error
Console.WriteLine(c.publicID);
}
}
Other objects can access NumberOne, but they can't access numberTwo.
So I can do Your_Object.numberOne = 14; but I can't do Your_Object.numberTwo= 14;
Now I might be able to access the numberTwo through reflection depending on the permissions set up in the application, but I can't directly.
Variables in C#
Reflection in C#
Accessors in C#
in general, PUBLIC means any other code outside the class can change its value. PRIVATE are only able to be used/changed IN the class itself. Additionally, if you build classes that are derived from another, and you want the child-level class to be able to use/change values of its parent, but not other generic code outside the class, use PROTECTED.
Search for "Encapsulation".
There are so many easy materials to study it.
In the simplest terms numberOne being marked as public means that if you create an instance of your hithere class this member variable will be accessible. For example:
hithere h = new hithere()
h.numberOne = 42;
numberTwo being private means that this is not accessible and can only be used within the hithere class. So taking the above example further:
hithere h = new hithere()
h.numberOne = 42;
h.numberTwo = 84;
The last line would cause a compiler error as you cannot access numberTwo as this is private.
It is probably worth spending some time reading up on access modifiers, a quick google will find many examples, e.g:
http://www.devsource.com/c/a/Techniques/Understanding-C-Class-and-Member-Modifiers/
http://msdn.microsoft.com/en-us/library/ba0a1yw2%28v=vs.80%29.aspx
Additionally your hithere class does not have an access modifier defined therefore the compiler assumes this to be private. As such if you were to reference your library from another you would not be able to create instances of the hithere class.
public and private are access modifiers for members. This refers to who can access the members directly through code. public means that access is not limited so that anyone can access the member directly through code. private means that access is limited only to the containing class. So everyone can access numberOne directly through code, but only the containing class can access numberTwo directly through code.
There are a total of five access modifiers:
public: access is not limited
protected: access is limited to the containing class or classes derived from the containing class
internal: access is limited to the containing assembly
protected internal: this is an OR of protected and internal so that access is limited to the containing class or classes derived from the containing class OR the containing assembly
private: access is limited to the containing class
Note that the clause "directly through code" is critical here; it is possible to access these members using reflection.
The relevant section of the C# specification is §3.5, especially §3.5.2.
It means that if you have another class like this:
namespace hi
{
class hithere2
{
static void yo2()
{
hithere h = new hithere();
h.numberOne = 2;
h.numberTwo = 3;
}
}
}
The second one errors, but the first is OK.