How does the Setters and Getters in C# implement Encapsulation? I am not new when it comes to these setters and getters, I have background with programming, specifically java. in java you use setters and getters like this
public class Person {
private String fName;
public void setName(String someName) {
fName = someName;
}
public String getName() {
return fName;
}
}
public class Test {
public static void main(String[] args) {
Person p = new Person();
p.setName("Bob");
System.out.println(p.getName());
}
}
And in C# Using Shorthand
public class Person {
public string fName{ get; set;}
}
How does the C# shorthand getters and setters implement encapsulation on this? how do I implement that C# code the same as the java code above? are there any restrictions regarding it? and base from my observation, I can only use that "fName" if its set to public, specifically "public string fName{ get; set;}" but when it comes to private I cannot. but when i set it to private, I can no longer access it in other methods.
They don't allow you to specify encapsulating behavior. What they do is allow you to specify that this is a Property in the public interface of your class, as opposed to a field.
The difference here is that in Java, getters and setters are simply methods that follow a certain convention (getXXX, setXXX). In C#, properties are a first-class construct (even though they are basically getters and setters behind the scenes). So C# provides these as a shorthand way of saying you might implement encapsulation later (e.g. add behavior to the getter or setter) but you don't want to break consumers of your class, so you are declaring them as properties up front.
In Java:
public class Foo {
private String fooName;
public String BarName;
public String getFooName() { return fooName; }
public String setFooName(String fooName) { this.fooName = fooName; }
}
In C#:
public class Foo {
public String FooName { get; set; }
public String BarName;
}
Lets assume you have a consumer class FooReader defined in another assembly that references the Foo assembly:
public class FooReader {
public String ReadFoo(Foo foo) {
// This returns the Foo **property**
return foo.FooName;
}
public String ReadBar(Foo foo) {
// This returns the Bar **field**
return foo.BarName;
}
}
Now, changing Foo to this doesn't break FooReader:
public class Foo {
private String _fooName;
public String FooName { get { return _fooName.ToUpper(); } set { _fooName = value; } }
public String BarName;
}
but changing Foo to this WILL break FooReader- you'll need to recompile it:
public class Foo {
private String _fooName;
private String _barName;
public String FooName { get { return _fooName.ToUpper(); } set { _fooName = value; } }
// This breaks FooReader because you changed a field to a property
public String BarName { get { return _barName.ToUpper(); } set { _barName = value; } }
}
As you say yourself, the C# version is a shorthand for the following:
private string _name;
public Name
{
get { return _name; }
set { _name = value; }
}
(Note that the private field isn't accessable, it's compiler generated. All your access will be via the property, even from inside the class)
In comparision to java, where getter/setter are simply methods, this construct is called a property in C#, and is a compiler feature.
In, C# the equivalent of the code inside your Person class would be:
private String _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
As of C# 3, you can condense that down to:
public string Name { get; set; }
This is an automatically implemented property and the compiler will automatically generate the same encapsulating code as it will if you were to write it out the long way. A private backing field is automatically generated for you, as well as the get
and set
methods. Really, once the compiler generates the IL code, what you'll have is a field with two methods, get_Name
and set_Name
, so by using the auto-implemented property, you're letting the compiler generate nearly the same code as you have in your java example.
I'm going to modify your question slightly to provide a better comparison. In Java you commonly have public getters and private setters, with the constructor being the initializor[sic] of the variable, such as:
public class Person{
private String fName;
public Person (String name) {
setName(name);
}
private void setName(String someName){
fName = someName;
}
String getName(){
return fName;
}
}
With a user of the class only being able to retrieve the value after initialization through the constructor:
public class Example {
Person person = new Person("Fred");
System.out.println(person.getName()); // Allowed
System.out.println(person.fName); // Not allowed because fName is a local class variable
person.setName("Aaron"); // Not allowed because setName() is a local class method
}
Now this is where C# can become confusing, as instead of using Person.getName
you simply use the variable itself, however this variable can still be encapsulated. In Java you are taught that Class variables should be local (private) and should only be accessed with getters and setters. C# is essentially the same, but the syntax and logic is different. Rewriting my example in C# would be:
public class Person {
public String fName {get; private set;}
public Person(String name) {
this.fName = name;
}
}
public class Example {
Person person = new Person("Fred");
Console.WriteLine(person.fName); // This is allowed
person.fName = "Tony"; // Not allowed because setter is private
}
Now if you wanted to add logic to your getter and setter using the above conventions, you would need to introduce a local private variable, but the code in Example
and your Person constructor wouldn't change:
class Person {
private String _fName;
public String fName {
get { return _fName + ".addedText"; }
private set { _fName = value.ToLower(); }
}
public Person(String fName) {
this.fName = fName;
}
}
Now whether this is better or worse than Java is somewhat debatable, but from what I've seen your code is going to be out of place in C# if you do something like the below, although syntax wise it will work:
class Person2 {
private String fName;
public Person2(string fName) {
setFname(fName);
}
private void setFname(String fName) {
this.fName = fName.ToLower();
}
public String getFname() {
return this.fName+ ".addedText";
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With