I'm studying this simple class and wondering what difference the private set of the Name property actually makes?
If that line simply read public string Name { get; } how would the user's interaction with the class change?
public class Contact2
{
// Read-only properties.
public string Name { get; private set; }
public string Address { get; }
// Private constructor.
private Contact2(string contactName, string contactAddress)
{
Name = contactName;
Address = contactAddress;
}
// Public factory method.
public static Contact2 CreateContact(string name, string address)
{
return new Contact2(name, address);
}
}
They are both read-only properties, and objects of this class can only be constructed via the static method, so does it matter if the set of name is private or not?
EDIT
It is part of this MSDN code:
https://msdn.microsoft.com/en-us/library/bb383979.aspx
In C# 6:
public string Name { get; private set; }
Can be set from any method within the class.
public string Address { get; }
Is a read-only property and can only (and must) be set on initialization.
In your code they're functioning the same way, however the read-only property enforces an additional constraint making the property immutable as it can only be set once, whereas you could add a method to the class which mutates Name making the class mutable.
Getter-only auto properties like public string Name { get; } were not allowed before C# 6.0, so the code would not compile. That's why you needed a private setter before.
See: Getter-only auto-properties.
Related
First up this is not a duplicate of AutoMapper mapping properties with private setters , because that deals with 'properties with private setters' not readonly setters. Although I would be happy to merge, if needed.
public class Example{
public string PrivateSetter { get; private set;}
public string ReadonlyProperty { get; }
}
Now that nullable reference types is a thing. I want to create dtos/models that follow that practice. however if I have a class with a property of say public string Name { get; set; } I get warnings that Name may be null. So I thought I would change the property to be a readonly property public string Name { get; } which I initialize in the constructor. Sweet! That made my null warning go away. But boom now at runtime my auto mapper dies. It cant find a parameterless constructor.
Now one way around this is to setup my mapper like this:
public class SourceClass
{
public string Name { get; }
}
public class DestinationClass
{
public DestinationClass(string name)
{
Name = name;
}
public string Name { get; }
}
Mapper.CreateMap<SourceClass, DestinationClass>()
.ConstructUsing(s => new DestinationClass(s.Name));
However that is pretty rubbish! As I now need to manually map every property, in the correct order, in the .ConstructUsing() method. Which kinda defeats the point of using Automapper.
So my question is How can I map to a class, with read only properties, using Automapper; without having to use .ConstructUsing()` and manually map every property into the constructor?
I'd like to create a class for my website with a lot of private variable.
I thought there was a solution not to write all the getters and setters for each variable, something like
private int confirmed { get; set; }
Is it the right way? ANd then, how do I access this value from outside the class?
I've tried .confirmed , I get the error saying that it's private (which I understand)
But more surprising, .getConfirmed() or getconfirmed() do not work either.
I thought that the { get; set; } would create implicitely those methods.
Can someone clarify this concern for me please?
You can declare your property as public, then mark the getter or setter individually as private:
public int confirmed { get; private set; }
That way, you can access confirmed outside of your defined class:
Console.WriteLine(myClass.confirmed); // This is OK
myClass.confirmed = "Nothing"; // Can't do this
And the only one who can set the value of confirmed is then MyClass:
public class MyClass {
public int confirmed { get; private set; }
public MyClass() {
this.confirmed = "This"; // This is fine as we have private access
}
}
You need to understand that,
private int confirmed { get; set; }
will be expanded to a set of private methods with a private backing field,
private int _confirmed;
private int confirmed_get()
{
return this._confirmed;
}
private void confirmed_set(int value)
{
this._confirmed = value;
}
Thus, marking the property private makes both the accessor and the mutator also private, which is why you cannot access them outside of the class. Also, these methods are not accessible at compile time, so calling instance.confirmed_get() is not permitted, only instance.confimed both to read and write to the property.
What you might want is to declare it public,
public int confirmed { get; set; }
where the behavior is similar (the field still is private), but both method are now public. As others have mention you can individually modify the get and set for readonly or writeonly type of behavior,
public int confirmed { get; private/protected set; }
or
public int confirmed { private/protected get; set; }
And one last thing, you should get into the habit of using camel case for propeties, e.g. Confirmed and lower camel case for fields, e.g. confirmed (some might even do _confirmed). It is a popular naming conventions to distinguish the two types, especially for consumers of the class.
how do I access this value from outside the class?
You can't (without reflection form trusted code). They're private. If you want the getter to be public but the setter private then do
public int confirmed { get; private set; }
I thought that the {get;set;} would create implicitly those methods.
It does, but they're not accessible at design time.
Just do this if you want to get it from outside the class.
public int confirmed { get; set; }
or you can go this route:
private int confirmed;
public int Confirmed
{
get { return confirmed }
set { confirmed = value; }
}
There are multiple ways to perform such action. Depending upon your requirements, you can choose any one method from below:
// Old Conventional - Statement body
public class SampleClass1
{
public bool CanAccessFromOutside
{
get { return _cannotAccessFromOutside; }
}
private bool _cannotAccessFromOutside;
private void DoSomething()
{
_cannotAccessFromOutside = true;
}
}
// Expression Bodied Property
public class SampleClass2
{
public bool CanAccessFromOutside => _cannotAccessFromOutside;
private bool _cannotAccessFromOutside;
private void DoSomething()
{
_cannotAccessFromOutside = true;
}
}
// Auto Property
public class SampleClass3
{
public bool CanAccessFromOutside { get; private set; }
private void DoSomething()
{
CanAccessedFromOutside = true;
}
}
I am learning C# and i have encounter the following piece of code
public class Album
{
public virtual int AlbumId { get; set; }
public virtual int GenreId { get; set; }
public virtual int ArtistId { get; set; }
public virtual string Title { get; set; }
public virtual decimal Price { get; set; }
public virtual string AlbumArtUrl { get; set; }
public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
}
just wondering what's the different with the following? i mean without the get and set you can access those public property as well. what's make it important to have those get and set?
public class Album
{
public virtual int AlbumId;
public virtual int GenreId;
public virtual int ArtistId;
public virtual string Title;
public virtual decimal Price;
public virtual string AlbumArtUrl;
public virtual Genre Genre;
public virtual Artist Artist;
}
To have control over your object private fields values. for example if you don't wanna allow nulls or negative values for integers.
bool started;
public bool Started
{
get { return started; }
set
{
started = value;
if (started)
OnStarted(EventArgs.Empty);
}
}
another example
int positiveNumber;
public int PositiveNumber
{
get { return positiveNumber; }
set {
if (value < 0)
positiveNumber = 0;
else positiveNumber = value;
}
}
and also another implementation of read only properties could be as follows
int positiveNumber;
public int PositiveNumber
{
get { return positiveNumber; }
}
You can't declare a virtual field
public class Album
{
public virtual int AlbumId; // <- Syntax error
...
}
properties are, in fact, methods: get or(and) set, so
public class Album
{
public virtual int AlbumId { get; set; } // <- Both get and set methods declared as virtual ones
...
}
And you can override these get's or(and) set's in derived class if you want:
public class GreatAlbum: Album {
private Boolean m_IsGreat;
public override int AlbumId {
get {
if (m_IsGreat)
return base.AlbumId
else
return 0;
}
set {
m_IsGreat = (value != 0);
base.AlbumId = value;
}
}
...
}
With providing get(accessor) and set(mutator) methods, you can control accessing and mutating.
For example:
You have a property that you don't want to be set any value more than 15. So u make required restrictions in your set method. Unless that set method, you can't control.
But in your example, your get and set methods are default, means controlling nothing.
The main reason behind properties is to protecting and presenting private data in a controlled way.
In fact, properties show their abilties in the usage like this:
public virtual int AlbumId
{
get { // ... some magical operations ... }
set { // ... some magical operations ... }
}
And about your main question - what's the difference in this example - the main point to attention is the virtual keyword.
This keyword causes the property to be overrideable, So any other code could override the default get; method. It meens that you have the default behavior for yourself, and other codes (Extremely used in Entity Framework) implement their own logic!
Those second ones in your example aren't properties, so they don't express this magical ability...!
In the first case you are dealing with properties, in the second with fields.
Using fields has several drawbacks when compared to using properties. These drawbacks include:
You can set a breakpoint in a get or set of a property, but you can not set a breakpoint on access to the field.
Making fields public violates the information hiding principle.
The binary MSIL code for accessing fields and properties is different, so if you change a public field to a public property in the future, although the source code stays compatible, any dependant binary code breaks.
The code required to use reflection is different, hence when you move from a field to a property, your reflection code will break.
To cut a long story short: Always use public properties, NEVER use public fields.
There are a number of differences:
Properties are turned into methods by the compiler. As such, you can declare them virtual and override them in a derived class.
Using properties, you can put logic in the getter or setter (filtering, validation etc).
When you use automatically implemented properties ({ get;set;}), it may seem that you might as well just use public fields. However, using properties means you can change your getter or setter implementation at a later time, without changing the interface your class is exposing. If you had used a field and wanted to implement filtering whenever that field was read, you would have to introduce a new method, make the field private and break all existing consumers of the type.
Personally, I think the automatically implemented properties promote bad style, because they do not encourage encapsulation. Tools like ReSharper also like to generate properties with {get;set} accessors. Novice developers thus typically end up with classes with lots of {get;set;} properties exposing the type's state to the world. You should at least use {get; private set;} by default.
I have a public class
public class Interview
{
public int InterviewId;
public string ApplicantName;
...
public List<AnsweredQuestions> AnsweredQuestions;
public Questionnaire questionnaire;
}
and use it in a main program like this:
Interview interview = new Interview();
interview.InterviewId = 1;
and a Questionnaire class
public class Questionnaire
{
public int questionnaireId;
public string outputFile;
...
}
How can I prevent modifying the attribute int the main program:
interview.questionnaire.outputFile
I found I was able to use the DocumentManager class in the main program like this:
interview = documentManager.GetInterviewSession();
interview.questionnaire = documentManager.GetQuestionnaireManagement();
interview.AnsweredQuestions = documentManager.GetInterviewAnsweredQuestions();
by using this
public class DocumentManager
{
private readonly Interview _interview;
...
public DocumentManager(Interview interview)
{
_interview = interview;
}
I'm sure I should be encapsulating, but I'm not sure how. Any help would be appreciated.
Thanks!
I'm not sure I entirely get the question, but this is the usual method for read-only encapsulation:
public class Questionnaire
{
public string OutputFile { get; private set; }
}
This creates a property named OutputFile that can be read publically, but only written by the Questionnaire class.
Alternatively, you may want to use protected set; if you want classes deriving from Questionnaire to be able to set OutputFile.
If you need certain properties to be immutable then you can supply those properties in the constructor of the class.
Also instead of using fields, you can use properties that allow you to dictate whether the property getter and setter are private/public/internal/protected.
In your sample, you could have InterviewId as a property with a public get accessor and a private only set accessor. This means that only the class itself can set the interviewId. If the only way to set the interviewId is at the constructor of the class, then there is no way for the consuming code to change it (other than by using reflection of course)
public class Questionnaire
{
public Questionnaire(int questionnaireId, string outputFile)
{
QuestionnaireId = questionnaireId;
OutputFile = outputFile
}
public int QuestionnaireId {get; private set;}
public string OutputFile { get; private set; }
...
}
Simple question: does an abstract property create a private backing field? Example:
public abstract Name { get; set; }
Will this create a private backing field? I want to force any class that derives this property to use their own backing field, not one that's created by the compiler.
No it doesn't. I just tested with the following class:
public abstract class Class1
{
public abstract string TestStringAbstract { get; set; }
public string TestString { get; set; }
}
and decompiled it in Reflector. This was the generated code:
public abstract class Class1
{
// Fields
[CompilerGenerated]
private string <TestString>k__BackingField;
// Methods
protected Class1()
{
}
// Properties
public string TestString
{
[CompilerGenerated]
get
{
return this.<TestString>k__BackingField;
}
[CompilerGenerated]
set
{
this.<TestString>k__BackingField = value;
}
}
public abstract string TestStringAbstract { get; set; }
}
As you can see only a single backing field was generated for the concrete property. The abstract one was left as a definition.
This makes logical sense since the property must be overridden by any child class there is no point in creating a backing field that there would be no way of ever accessing (since you can't ever access the abstract property).
On the other hand a virtual property will create a backing field and any class that overrides the property with an auto-implemented replacement will create its own backing field at that class's level.
No. Since it's abstract, the class implementer must implement the property. If the implementer declares it that way, then Yes, it's an automatic property with a hidden member to hold the actual value.
There's a difference between:
public abstract string Name { get; set; }
and
public string Name { get; set; }
The first property declaration doesn't create a backing field. It just creates an abstract property (kind of like an interface method declaration), which has to be implemented by any non-abstract inheriting class.
The second declaration is an auto-property, which DOES create a backing field. It's actually compiler syntactic sugar shorthand for:
private string _name;
public string Name { get { return _name; } set { _name = value; } }