Clearing up property and field confusion in C#? I understand that creating public properties that control private fields is good practice because of coupling and encapsulation, although lately I have seen it as such a waste of boilerplate code for a simple entity class like below.
Take this class for instance,
public class PersonEntity
{
    private string _firstName;
    private string _lastName;
    private int _age;

    public class PersonEntity(string firstName, string lastName, int age)
    {
        _firstName = firstName;
        _lastName = lastName;
        _age = age;
    }

    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value; }
    }

    public string LastName
    {
        get { return _lastName; }
        set { _lastName = value; }
    }

    public int Age
    {
        get { return _age; }
        set { _age = value; }
    }
}

If all I am using is the property, is it okay to refactor the class to look something like this?
public class PersonEntity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public class PersonEntity(string firstName, stirng lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }
}

Or maybe even this is more simple (using object initialization to construct):
public class PersonEntity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

Which one should I implement if all I want to use the entity for is to map data from a database, and use it as a model to write to the database at a later date than when it was created?
Which versions should I use, when should I use them, and for what reasons should I use each one?
There is a special use case when the (slightly modified) second approach could be beneficial. Namely when you want to create immutable objects.
public sealed class PersonEntity
{
    public string FirstName { get; }
    public string LastName { get; }
    public int Age { get; }

    public PersonEntity(string firstName, string lastName, int age)
    {
        FirstName = firstName;
        LastName = lastName;
        Age = age;
    }
}

By removing the setters you are not allowing the consumer of the class to alter its data after creation. In case of concurrency immutable structures can be shared safely between multiple workers without extra syncronization.
You can define with method(s) to this class as an extension to provide copy with alternative value functionality.
public PersonEntity WithFirstName(string firstName)
{
    return new PersonEntity(firstName, LastName, Age);
}

public PersonEntity WithLastName(string lastName)
{
    return new PersonEntity(FirstName, lastName, Age);
}

public PersonEntity WithAge(int age)
{
    return new PersonEntity(FirstName, LastName, age);
}

Of course you can make it a bit more generic:
public PersonEntity With(string firstname = null, string lastName = null, int? age = null)
{
    return new PersonEntity(
       firstName ?? this.FirstName, 
       lastName ?? this.LastName, 
       age ?? this.Age);

}

Usage sample:
var xy = new PersonEntity(&quot;x&quot;, &quot;y&quot;, 15);
var xz = xy.With(lastName: &quot;y&quot;);
var xz25 = xz.With(age: 25);


UPDATE: C# 9's record
In C# 9 there will be a new construction called record.
Declaration
public record PersonEntity
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
    public int Age { get; init; }
}

Usage
var xy = new PersonEntity { FirstName = &quot;x&quot;, LastName = &quot;y&quot;, Age = 15 }; 
var xz = xy with { LastName = &quot;y&quot; };
var xz25 = xz with { Age = 25 };