Hola.
La diferencia principal y de forma resumida es que una variable es tan solo una variable, mientras que una propiedad es un miembro que encapsula dos métodos para proveer la funcionalidad de leer o escribir alrededor de una variable.
Primero hay que aclarar que si tomásemos el ejemplo que has puesto tal cual, de forma literal, entonces entre
public nombre as string y
property nombre as string no habría ninguna diferencia significativa que valiese la pena mencionar, puesto que más que de una propiedad estaríamos hablando de una
propiedad auto-implementada:
https://msdn.microsoft.com/en-us/library/dd293589.aspx -es decir, un tipo de propiedad en la que Visual Studio se haria responsable de su implementación Get/Set y de la variable de apoyo (o backing field) de forma automática, privándonos así de poder controlar esas funcionalidades básicas de una propiedad.
Sin embargo, si modificásemos tu ejemplo para dejar la definición de una propiedad tal que así:
Public Property MyProperty As String
Get
Return Me.myBackingField
End Get
Set(ByVal value As String)
Me.myBackingField = value
End Set
End Property
Private myBackingField As String
...entonces ya habría una diferencia muy destacable. Por un lado tendriamos una simple variable, y ahora tendriamos una propiedad que encapsula dos métodos,
Getter y
Setter alrededor de esa variable, lo que nos permitiría imiplementar métodos de validación para obtener y/o asignar el valor de esa propiedad. La diferencia es muy grande, igual que el control y la responsabilidad que obtendriamos sobre el comportamiento de nuestro código.
A este punto cabe mencionar que podemos definir una popiedad en modo sólo-lectura:
Public ReadOnly Property MyProperty As String
Set(ByVal value As String)
Return Me.myBackingField
End Set
End Property
Private myBackingField As String
o en modo sólo-escritura, siendo esto último una diferencia imposible de reproducir en una variable.
Public WriteOnly Property MyProperty As String
Set(ByVal value As String)
Me.myBackingField = value
End Set
End Property
Private myBackingField As String
Otra diferencia muy importante entre una propiedad y un valor de campo o variable es el propósito de ambos tipos de miembros. Una variable por ejemplo no se puede declarar al definir una interfáz:
Public Interface IMyInterface
Public MyField As String
End Interface
Sin embargo, una propiedad sí:
Public Interface IMyInterface
Public Property MyProperty As String
End Interface
Y cuando estemos trabajando con una clase, una variable suele ser declarada con una visibilidad privada (o al menos así debería ser declarada) para impedir su acceso y/o su modificación desde otros niveles superiores de accesibilidad de clase, por otro lado una propiedad suele ser un miembro declarado con una visibildidad pública para exponer como ya hemos dicho un mecanismo de lectura y escritura alrededor de una variable (una variable con visibilidad privada).
Dentro del propósito de cada miembro entraríamos a mencionar las diferencias de representación que tienen cada uno de estos miembros en tiempo de diseño...
Tenemos por ejemplo una clase que hereda de la clase
UserControl, nuestra intención es diseñar un control personalizado que cumpla "X" propósito y para ello queremos exponer un miembro público para que el usuario pueda modificar en tiempo de diseño el color del borde del control (por poner un ejemplo sencillo y aleatorio) mediante el diseñador o designer del control en Visual Studio. ¿Cómo lo hariamos?, pues muy necesariamente tendriamos que exponer esta funcionalidad a través de una propiedad (ya sea auto implementada o no) como por ejemplo así:
<DesignTimeVisible(True)>
<ToolboxItem(True)>
Public Class MyControl : Inherits UserControl
<Browsable(True)>
<Category("Appearance")>
Public Property BorderColor As Color
End Class
...Puesto que si intentásemos reproducir la misma funcionalidad con una variable entonces no se representaría ningún mecanismo de lectura y escritura en tiempo de diseño en el diseñafor del control, por lo que no serviría de nada usar una variable en un escenario como este:
<DesignTimeVisible(True)>
<ToolboxItem(True)>
Public Class MyControl : Inherits UserControl
<Browsable(True)>
<Category("Appearance")>
Public BorderColor As Color
End Class
Hay varias diferencias más, como por ejemplo la ventaja de poder hacer databinding gracias a una propiedad y no a una variable, o las diferencias de serialización entre cada tipo de miembro, pero bueno, creo haber explicado las diferencias más notables e importantes en el uso cotidiano que un programador común le suele dar a este tipo de miembros, y no quiero excederme demasiado más alargando este post.
PD: Todas estas reglas o diferencias que he mencionado se aplican también al lenguaje C#.
¡Saludos!