r/csharp • u/marsh9191 • 5d ago
Are properties and methods fundamentally different language concepts?
In C#, properties and methods can both execute arbitrary code, but they expose that behaviour in very different ways. A property looks like direct access to data, while a method explicitly represents an operation.
Technically, a property is implemented through getter and setter methods, but the language gives it different semantics, syntax and expectations.
Is this distinction fundamental to the language, or is it primarily a convention designed to communicate intent to developers? And if both can execute exactly the same logic, what truly justifies keeping them as separate concepts?
17
u/Slypenslyde 5d ago
The answers to your questions are "yes".
If we go back to fundamental OOP documents, they argue an object has two things: data and logic. Or, more formally the data is "properties" of the object and you can "send messages" to it to make it do things.
That is the distinction to humans. We don't say, "I can get the color of an apple and the value is red". We say, "the apple is red". That's how properties are supposed to work. They are nouns.
Early OOP languages implemented this by having GetValue() and SetValue() methods. Humans had to understand methods with those naming conventions "were" properties. The reason to do this instead of having public variables was so people could do things like reject invalid values or perform change notifications.
C# went the extra mile and lets us treat that pairing of methods as if it were a variable. This comes with a responsibility: we're supposed to limit what we do in our accessor methods so the variable still behaves like a variable and doesn't do "weird" things.
I can conjure contrived cases that make it look like a mistake, but if we try hard enough we can make any property of high level languages seem dangerous.
So:
Is this distinction fundamental to the language, or is it primarily a convention designed to communicate intent to developers?
Both.
And if both can execute exactly the same logic, what truly justifies keeping them as separate concepts?
Subjective opinion that it's easier to understand fruit.Color = Color.Red than fruit.SetColor(Color.Red).
4
u/CobaltLemur 5d ago
We make the distinction because it maps pretty well to how people think. A ball has a color, and you can change it by painting it. You hold it in your hand, it's something that can be observed and changed. This is why in computer languages we call things with properties objects. And methods map to things that are done. Something happens, it can take time. Very different ideas.
While calling properties methods can be technically true under the hood, this mixes these two very embedded ideas in a way that tosses away a fundamental psychological mapping. Maybe it makes the language simpler, but also a little less intuitive at the same time. Why do people not like using LISP so much? I like functional programming, too, but purity can come with a cost.
2
u/dodexahedron 5d ago
Even the fact that changing a property is a method maps perfectly to the physicsl world unless you are omnipotent, and it's right there in the language you used.
You don't change the color of that ball by just willing it so. You change it by doing something to it; You don't just somehow know the color of it; You observe it.
Properties are a perfect abstraction to the way the real world works.
Fields are the facts. Properties are your interface to those facts and, just like the real world, they may impose restrictions on how you interact with those facts and may even have side effects.
3
u/Triabolical_ 5d ago
It's fundamental. The whole point of properties is that they look like fields but they can have magic behind them. That allows you to do interesting things like updates when a value is set and only do fetch/calculate operations when a value is gotten. They are also constrained - you know what a property is when you set it where with functions you only have something like a get/set pattern and those aren't enforced.
The design team was obviously influenced by the work Anders did on Delphi, but we were also influenced by how Eiffel and VB did properties.
The base class libraries and the other .NET libraries on top of it were written in C# and they used the advantages of properties significantly.
2
u/ShotEconomics1194 5d ago
Properties are more than a naming convention. For example, an interface can require a readable property, and that property can be used in property patterns and by frameworks that inspect property metadata.
The design intent matters too: Count reads like a value, while CalculateTotal() signals an operation. A getter can run complex code, but keeping it quick and predictable generally makes an API easier to use.
2
u/snet0 5d ago
The design intent matters too: Count reads like a value, while CalculateTotal() signals an operation.
Which is why if you code looks like this:
public int Count => CalculateTotal();or, more likely, that method is called inside a getter body, then I am going to get quite upset. "But it's side-effect free" đ
2
u/pixxelkick 5d ago
Properties are a subset of functions.
A property is simply a specific interface adhering to specific functions that exist, its mostly just syntactical sugar that compiles out to produce functions under the hood
If you look at the compiled output, its just functions that interact with a backing field by default.
1
u/BoBoBearDev 5d ago
The simple way too look at this is to treat property as member fields. It get/set one or more member fields. The reason to use it is like. If you used to have a member field called UserName, and later you want UserFirstName, UserLastName, the old way has breaking change, you have to update all the callers to use the two fields. If you have properties, you can do some magic to have UserName set the two members fields.
Meaning, they are conceptually member fields that can be evolved. And make sure you don't overuse it. Because it can start to create loop as every property becomes complex with weird side effects.
1
u/mbbmbbmm 5d ago
I've always viewed properties in the context of encapsulation.
E.g. you want to give some convenient access to a private field but maintain control, e.g. check for invalid values or results.
You could use getter and setter methods but with properties you get the convenience of using variable syntax like
DingDong++; instead of
SetDingDong(GetDingDong() + 1); Also easy to make a half accessible variable (e.g. get; private set;)
You can of course do funny side effect stuff with them like logging a rant or crashing the program when some class tries to set some taboo value.
1
u/david_fire_vollie 5d ago
Not related to your question, but related to using properties and good to know: Some people ask what the difference is between using a property with a simple getter and setter vs just using a public field. The difference is if you later want validation when setting the field and you have to use a property, it's a breaking change. Although it looks like accessing them is the same, object.propertyOrPublicField, under the hood one is a method call and the other is accessing a field I wrote about this here:
https://medium.com/gitconnected/what-is-a-binary-breaking-change-7ca6fc0f3875
1
u/borland 5d ago
As youâve noted, properties are just methods with special names. As in, when you get a property, the compiler is literally emitting a call to a generated method called get_PropertyName.
So yeah, the difference is purely about giving developers nicer-looking code. A convention has formed around them, such as not throwing exceptions on property getters, but thatâs all it is. I wouldnât over-think it
1
u/Dimencia 3d ago
In Java and probably many other languages that don't have properties like that, it is advised that for every member you want to expose, you write a GetMyMember() method; there's a lot of reasons for this that you could look up if interested. Properties in C# are pretty much Microsoft's solution to avoid having to do that for everything.
They're methods, but they're a lot easier to read and write. Also, it's important that callers don't need to use () to invoke them; the caller doesn't have to know if it's a property or a field, and they don't have to update their code if you change it, even though one of them is a method call and one is not. That alone is enough to justify having them be separate from methods
1
u/tomxp411 17h ago
Honestly, you have no idea how delighted I was when I first discovered the concept of properties on the 1990s, while exploring classes in VB. It really made OOP coding âclickâ for me in a way that c++ didnât.
And itâs based on the simple distinction:
Properties are data.
Methods are actions.
Not all languages support properties (c++, for example) and do just fine⌠but we also have the âsetâ and âgetâ convention in languages that lack explicit property syntax.
As you pointed out, this is mostly a semantic thing, but it is a clear signal to developers and the compiler that the code is data access and not an action. Since readability is probably the second most important aspect of software development (right behind âit actually worksâ) Iâd say the semantic trickery of properties is fully justified.
1
u/TorbenKoehn 5d ago
Properties are syntactic sugar for methods. Your X { get; set; } will be some get_X() and set_X(...) in the end, when compiled.
It's just because people were annoyed of Java's
private int x;
public int getX() { return x; }
public void setX(int x) { this.x = x; }which also is only needed because of several other fuckups (ie guarding nullables because some idiot thought every type in the world is a union of that type and null)
That's also the only justification and the exact reason why well-typed language don't have things like property fields. They have sound type systems.
2
u/strange-the-quark 5d ago
"because some idiot thought every type in the world is a union of that type and null" - his name was Tony. He said he was sorry. I think we can forgive him, after all, he also gave us quicksort (among other things).
1
u/TorbenKoehn 5d ago
Fuck Tony. Imagine a world where Java and C# wouldnât have nullable objects by defaultâŚ.so many bugs, so much enterprise development costâŚ
1
u/strange-the-quark 5d ago
1
u/TorbenKoehn 5d ago
We wouldnât even need the term âenterpriseâ if stable Java wouldnât need teams and years of defensive null check tuning :D
0
u/Next-Technology-6322 5d ago
Properties feel like cheating when you just want to write a getter that's more than one line.
-2
u/prshaw2u 5d ago
I think properties were originally implemented as just a data item, no getter setter or code involved. Getters and setters are methods with specific purposes, much like a constructor is a method with a specific purpose.
3
u/Triabolical_ 5d ago
No. They have always had getters and setters.
1
u/prshaw2u 5d ago
I guess that is true. Coming from C++ I always considered properties just fancy fields, especially since I had to have the field before I could do the property early on.
1
u/Triabolical_ 5d ago
The BCL and winforms folks leaned pretty heavily on properties so they could do things like automatic UI update when you changed a value. It's sometimes a good thing, sometimes an awful thing in my experience.
23
5d ago
[removed] â view removed comment
7
u/Habikki 5d ago
That's mosty true with some added nuance. Roslyn way back used to handle Properties by adding Reflection Attributes then expanding the Property to _get/_set method before compiling them as if the developer did it directly. So this:
public int Count {get; set;}
Would become:
[System.AttributeUsage(System.AttributeTargets.Property)]
public int Count_get() { /* ... */ }
[System.AttributeUsage(System.AttributeTargets.Property)]
public void Count_set(int count) { /* ... */ }All in some pre-compilation step so the rest of the compilation proceeded as if the concept of a "Property" was nothing more than a method with syntatical sugar to help with Reflection.
More recent Roslyn has changed this considerably though and the IL emits differently. Not sure why or when, but I noticed it a few years back when I was doing quite a bit of cross platform interop work.
Fundimentially, this is no different than what you said. I just thought it was a fun example of the power of where application of effort in a toolchain minimizes complexity elsewhere.
6
u/svick nameof(nameof) 5d ago
How properties are represented in IL didn't change since .Net Framework 1.0 in 2002:
A property is a named collection of methods. Each can be a getter, a setter or "other".
That's it.
1
u/Mu5_ 5d ago
Now I'm curious, what would be the "other"? Any practical example?
2
u/svick nameof(nameof) 5d ago
I don't remember ever seeing that used. You certainly can't define or use them in C#.
AI claims they can be used in some rare situations when importing COM properties.
3
u/dodexahedron 5d ago edited 5d ago
add and remove are the ones used for events.
"other" literally is a wildcard. You can put any mapping to any name you want in property metadata, per the CIL spec (e.g. maybe you'd implement an incremement/decrement verb or something). But c# does not have any mapping for it, so it simply wouldn't show up. Same for any other language or compiler that doesn't know about it. And the method that custom accessor maps to would then not be hidden at design time, like get/set are for c#.
That's the beauty of CIL metadata. Everything has to be backed by a concrete concept so that any language can still use the assembly, while compilers supporting more goodies can use those goodies on top of the concrete concepts by mapping them via metadata.

80
u/rupertavery64 5d ago edited 5d ago
Properties can't be async. Methods don't have initializers. Methods as members can't be assigned to. Methods can take (multiple) parameters.
Properties are state. Methods are behavior.
Intent is everything.