There really isn't any difference. The property syntax is largely just a shortcut to writing a dedicated getter/setter method. The compiler will create a Get and Set method as well as a private backing field when using properties.
When looking at the Intermediate language you will see that the generated code is basically identical minus some attributes marking compiler generated code and odd looking compiler generated naming conventions. In both cases a private field is accessed by a getter/setter function.
Take these two different implementations:
//method 1
public int Property {get; set;}
//method 2
int property;
public int GetProperty() { return property;}
public void SetProperty(int value) { property = value; }
In IL you'll see the following for the method 1 getter:
//compiler generated backing field
.field private int32 '<Property>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
//compiler generated getter method
.method public hidebysig specialname
instance int32 get_Property () cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2050
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
//retrieves a backing field
IL_0001: ldfld int32 Test1.Program::'<Property>k__BackingField'
IL_0006: ret
} // end of method Program::get_Property
//your property
.property instance int32 Property()
{
.get instance int32 Test1.Program::get_Property()
.set instance void Test1.Program::set_Property(int32)
}
Then if you look at the IL for method 2:
.field private int32 'property'
.method public hidebysig
instance int32 GetProperty () cil managed
{
// Method begins at RVA 0x2050
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 Test1.Program::'property'
IL_0006: ret
} // end of method Program::GetProperty