C#: Getter/Setter

c#: getter/setter

Those are Auto-Implemented Properties (Auto Properties for short).

The compiler will auto-generate the equivalent of the following simple implementation:

private string _type;

public string Type
{
get { return _type; }
set { _type = value; }
}

Getter and Setter declaration in .NET

Properties are used to encapsulate some data. You could use a plain field:

public string MyField

But this field can be accessed by all outside users of your class. People can insert illegal values or change the value in ways you didn't expect.

By using a property, you can encapsulate the way your data is accessed. C# has a nice syntax for turning a field into a property:

string MyProperty { get; set; }

This is called an auto-implemented property. When the need arises you can expand your property to:

string _myProperty;

public string MyProperty
{
get { return _myProperty; }
set { _myProperty = value; }
}

Now you can add code that validates the value in your setter:

set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentNullException();

_myProperty = value;
}

Properties can also have different accessors for the getter and the setter:

public string MyProperty { get; private set; }

This way you create a property that can be read by everyone but can only be modified by the class itself.

You can also add a completely custom implementation for your getter:

public string MyProperty
{
get
{
return DateTime.Now.Second.ToString();
}
}

When C# compiles your auto-implemented property, it generates Intermediate Language (IL). In your IL you will see a get_MyProperty and set_MyProperty method. It also creates a backing field called <MyProperty>k_BackingField (normally this would be an illegal name in C# but in IL it's valid. This way you won't get any conflicts between generated types and your own code). However, you should use the official property syntax in C#. This creates a nicer experience in C# (for example with IntelliSense).

By convention, you shouldn't use properties for operations that take a long time.

How do I call a getter or setter in C#

localMyClass.myVal = 42;

Getters and setters let you treat the values like public properties. The difference is, you can do whatever you want inside the functions that do the getting and setting.

Examples:

store other variables

private int _myVal, myOtherVal;
public int MyVal { get; set { _myVal = value; myOtherVal++; } }

make numbers up / return constants

public int MyVal { get { return 99; } set; }

throw away the setter

private int _myVal;
public int MyVal { get { return _myVal; } set { ; } }

In each of these cases, the user will feel like it's just a public data member, and simply type

localMyClass.myVal = 42;
int i = localMyClass.myVal;

The gettors and settors let you make an implementation of your own. Also, as Hogan says, "There are a number of libraries and add-ons [e.g. MVC.NET] that require you to use getter and setter functions" - even if it's for the trivial {get; set;} case.

C# 6 getters and setters

Shorthand syntax with => only constructs a read-only property.

private int _id;
public int Id => _id;

This is equivalent to auto-property which is read-only:

public int Id { get; }

If you want your property to be both settable and gettable, but publically only gettable, then define private setter:

public int Id { get; private set; }

That way you don't need any private field.

Manipulating C# Shorthand Getter-Setter

No, you cannot have an auto-implemented getter and a custom setter (or vice-versa).

When you write:

T Prop { get; set; }

the compiler generates a special backing field for the property with a name that is inaccessible from actual C# code (disassembling .NET Core 3.1 compilation of the above code yields a name of <Prop>k__BackingField) and creates a straightforward getter that returns its value and a setter that assigns value to it.

Now, if either your set or your get is custom, there is no universal way of auto-generating a sensible counterpart. In your case the backing field width is of the same type as the property itself and has the same name, only in lowercase. But one could easily have a backing field that has a different type and a different naming convention. Or the property could be a complicated combination of many different fields.

As you can see, this breaks down pretty easily, so the only feasible way an auto-generated counterpart could be implemented is "if there is a field with the same name as the property but lowercase (or lowercase preceded by an underscore, as is the standard .NET naming convention) then auto-generate the counterpart using that field". That's very specific and the complexity of implementing it does not warrant its usability, since the difference between:

T _prop;

T Prop
{
get => _prop;
set
{
... // custom code
}
}

and

T _prop;

T Prop
{
get;
set
{
... // custom code
}
}

is negligible. I'd even argue that the first one is more readable, since it specifically shows me the field being used and I don't have to look for it.

C# setter/getter of two variables

You can try this

public int var1 { get;set;}

public int var2 { get;set;}

C# | get/set variable always returning null

_json = Json; will invoke the getter again, which returns the (old) value of the backing-field. So your current code is similar to this:

public static string get_Json() => _json;
public void set_Json(string value) =>
{
var newValue = get_Json(); // here _json just returns the old value
// you don´t use the provided value here
_json = newValue;
}

You need to use the value-keyword:

public static string Json
{
get { return _json; }
set {
_json = value;
Console.WriteLine("Json variable was modified. Now it's value is: " + _json);
}
}

C# - Using a private setter with a public getter on reference types

If the type you're referring to is mutable, then yes, anyone with a reference to the "container" can fetch a reference and then mutate the object. For example:

using System;
using System.Collections.Generic;

class Container
{
public List<string> List { get; private set; }
= new List<string>();
}

class Program
{
static void Main()
{
var container = new Container();
var list = container.List;
Console.WriteLine(list.Count); //0

container.List.Add("foo");
Console.WriteLine(list.Count); // 1
}
}

Here the List<string> is being mutated outside Container. One option to avoid this would be to use a read-only view over the mutable data:

using System;
using System.Collections.Generic;

class Container
{
private readonly List<string> list = new List<string>();

public IReadOnlyList<string> ListView { get; }

public Container()
{
ListView = list.AsReadOnly();
}

public void AddItem(string item)
{
list.Add(item);
}
}

class Program
{
static void Main()
{
var container = new Container();
Console.WriteLine(container.ListView.Count); //0

// container.ListView.Add("foo"); // Compile-time error

container.AddItem("foo");
Console.WriteLine(container.ListView.Count); // 1
}
}

Note that you shouldn't just return the list directly from the property, even if the compile-time type is IReadOnlyList<T> - because then a caller could just cast back to List<T> and mutate it. List<T>.AsReadOnly() returns a genuinely read-only wrapper object around the list, so callers really won't be able to mutate it.



Related Topics



Leave a reply



Submit