Is there a better way to do this (C#)? [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I really don't know what to put in the title, so don't read too much into it.
Anyway, to explain what I'm having trouble with is this. I have three classes: A, B and C. The class hierarchy is as follows:
A <-- B <-- C
(So A is the base class.)
The application in question is a database app. It queries information several tables (A is one table, and B and C are one) and stores it into an instance of C. That part works fine. The problem is when I want to update the table represented by B and C.
To avoid boilerplate code for each code, I use reflection to generate an update query from the class. But if I pass it an instance of a C class, it means it will also pick all the members from A, which is a separate table. Hence the update query will be wrong. And that's where my problem lies. I
want to get all members of B and C without writing a lot of boilerplate code and with a clean, scalable solution. I just don't know how.
(I currently use an approach where I pick all members of the top-level type, then search all of the class's parents and pick all those members and stop collecting members when it finds a specific parent type, e.g. A. This is an awful solution, I think.)
All these classes contains variables fetched from the database and have no methods or fields. Any good ideas on how to approach this problem? I hear C# does not have multiple inheritance, a tool perfect for this job (thanks C#!).
I hope I'm making myself clear.
EDIT1:
To address some questions and give additional context. First off, here's how my system looks today. To query data, I first have a class X, and a query text. The query is run against the database and returns some rows. Then each row is converted into an instance of X and added to a list. The code knows how to convert a row into an X by using reflection and looking at the actual variables in X and the name of the columns in the fetched database row. It then takes column A and places that information into the variable called A in X. So by making a class X and matching that to the database structure is all that's necessary to fetch another table of data.
Sometimes you need to fetch data from multiple tables and put them together. To do this, I need a class X that matches the information fetched from the query. There are a lot of data that I fetch and all this data has a common subset fetched from table A. The rest is fetched from a lot of other tables that contain additional data. Hence the type system always looks like something A <-- B, where A is the common subset of all data I fetch. This works great for queries. I can add additional data and a class and I'm done. No more boiler plate code.
But that's only half the story. I need to update these tables too (I don't need to update A). But to do that, I need to separate the data fetched from the table A, the common subset. Here's how I do the updating:
Connection.RunUpdateQuery(..., Utility.ToDictionary(Entry));
Where Entry is the class containing the information to update into the target table. So I convert the class into a Dictionary representing column name, column value and send that the RunUpdateQuery which generates an update sql statement and sends it to the database. Again, this is really nice because I have to write absolutely no boilerplate code.
But Utility.ToDicionary can't know what subset of information I actually want to insert. What it does is just take every variable in the class and transform it into a dictionary where the name of the variable is the column name (i.e. the key of the dictionary). In this case, if I pass it a C, I really only just want B and C because they're part of the target table I want to update. The A subset is part of another table which I don't want to update.
If there's a framework that does all this work, I'm all for it. But right now, I don't have the time to rewrite this code. So I'm going to have to wait with that that until later.
This is also my own database that I am designing. I'm in charge of everything regarding the project's design.
I really don't want to generate queries, even if it just means running a tool because a) it means more work every time the database changes and b) it means more bugs because I might forget to update certain places when something changes. With my current reflection-based solution, I don't have to change anything. I just have to design the database and an appropriate class (which I have to anyway since I need to translate the rows from the db into appropriate first-class citizens in the code so I can work with them more easily).
Using attributes doesn't seem like a good way of doing it either because it's all context-dependent. The caller that wants to update a table must be able to choose which fields should be updated in the database, but not at such a fine-grained level. The caller should simply be able to select the class to update, so to speak.
Maybe this gives some clarity into my problem.
EDIT2:
Examples of class A, B, C:
C:
public class PumpEntry: SignalEntryD
{
public uint? Addr;
public uint MasterlistIdx;
public bool MinDominant;
public uint? TriggerInterval;
public uint? SpDef;
public uint? MinDef;
public uint? MaxDef;
public uint? Step0Def;
public uint? Step1Def;
public uint? Step2Def;
public uint? Step3Def;
public uint? Step4Def;
public uint? Step5Def;
public uint? ExReqFacBACNet, ExSpFacBACNet;
public decimal? DeltaTX0Def, DeltaTX1Def, DeltaTX2Def, DeltaTX3Def;
public uint? DeltaTYMinDef, DeltaTY0Def, DeltaTY1Def;
public string DeltaTSensor1, DeltaTSensor2;
public int? ReqLimitMethodDef;
}
B:
public class SignalEntryD: DeviceEntry
{
public int? Channel;
public int? pCOeNum;
}
A:
public class DeviceEntry: DbType
{
public int Id;
public DeviceType Type;
public string Name;
public string CMCategory;
public bool Generate;
public new string ToString() { return Name; }
}

You should probably use an ORM library such as Entity Framework or NHibernate. They know how to deal with inheritance (they offer several strategies you can choose from). Then you don't need to write any boilerplate code at all.

I guess the typical C# solution for this is to mark your fields with custom attributes, and use that in reflection to decide whether or not it should be included.
public class DoSerializeAttribute : Attribute {}
public class C : B {
[DoSerialize]
public MyMember { get; set; }
}
And later in your reflexion code you can use GetCustomAttribute method.

You say you are using reflection. In thise case, doing this:
C myObject = new C();
myObject.GetType().GetProperties(System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.DeclaredOnly)
Should only give you the properties declared specifically in C, not in B or A. From there on you could use myObject.GetType().BaseType which would give you B, and its BaseType would be A.
Check it in this fiddle
I made a rough query generator here: check it in this other fiddle, which generates all update queries needed (if you pass a C, it'll generate queries for tables A, B and C), except for the types you pass as parameters.
With this information, you could easily generate your update queries dynamically and for any levels of hierarchy.
I'd give you more specific code but you wrote none
Not saying this is the perfect solution, but it's what you are asking for in your question

Without learning ORM (which is a proper thing, but may be overkill in a simple case and by saying overkill I mean learning curve) you can use LINQ-to-SQL as model to access your data instead of creating C class yourself. Create dbml file (see e.g. here regarding what is it). As result you get you table class code-generated, then you just use it
using (var context = new SomeContext()) // static connection string
{
var query = context.SomeTable.AsQueryable();
if (SelectedFilter == Today)
query = query.Where(o => o.Id >= DateTime.Today);
...
// constructing ViewModel items (WPF, MVVM)
foreach (var item in query)
items.Add(new Item()
{
Id = item.Id,
...
}
}
Item (B in your example) is a simple class to hold values. You can populate other properties of Item using another query or context (another table or database).
When you want to update database you simply do
using (var context = new SomeContext())
{
var change = context.SomeTable.First(o => o.Id == item.Id);
change.Comment = item.Comment;
...
context.SubmitChanges();
}
Basically you write those methods once for your ready-made ViewModel item (can be a complicated query to many tables or multiple queries to different databases). Updating part can be methods of Item or, better, of ViewModel (because it can be optimized, e.q. when only changing Comment you don't need to update other fields and perform other queries).
Boilerplate? Not really, look into SomeContext generated cs-file to see some.

To be frank, I personally think your current solution is a mess. There are infinte amount tools available for this kind of stuff, why reinvent (and very badly to be honest) the wheel?
Anyhow, trying to solve your issue in your particular setup, here is what I'd do:
First off, get rid of inheritance. You shouldn't be using it at all. Inheritante is most definitely not a tool meant to be used as a means to avoid data duplication, the simple notion is horrendous.
You have 2 distinct tables in your DB, code them as such.
DbType
PumpEntry
I have no idea why you need the intermediate SignalEntryD. If its not a table in your DB then it shouldn't appear anywhere in your code (I'm guessing its also due to code duplication).
Be consistent: if fields Channel and pCoeNum are duplicated throughout different tables in your database then just duplicate them in your entities. Otherwise, create a table in your DB and then model it in your entities (as you do with DbType). Don't mix things up, do it the same way on both ends.
For reasons that become clear later on, make both your entities implement a "dummy" interface ITable (type safety) and a default parameterless constructor (including all your properties / fields of course).
Now the problem is, if I understand correctly, that you are receiving a Dictionary<string, object> with user updated values and you need to update a given table, the problem being that the dicitonary can contain fields that belong to different tables (I won't get into how you ended up with this problem to begin with, I'll just ride along...).
Well then, simply create a way to build any entity from a random dicitionary using reflection (my code uses properties, but it is equivalent with fields):
public static T CreateTable<T>(IDictionary<string, object> values) where T: ITable, new()
{
var table = new T();
foreach (var propInfo in typeof(T).GetProperties())
{
if (values.ContainsKey(propInfo.Name))
{
propInfo.SetValue(table, values[propInfo.Name]);
}
}
return table; //note that any property not defined in the dictionary will be initialized to the field's type default value.
}
And now, you'd use it as follows:
Connection.RunUpdateQuery(..., CreateTable<TableC>(Utility.ToDictionary(Entry))); //only fields of TableC will be passed along.

Related

MongoDB: How to define a dynamic entity in my own domain class?

New to MongoDB. Set up a C# web project in VS 2013.
Need to insert data as document into MongoDB. The number of Key-Value pair every time could be different.
For example,
document 1: Id is "1", data is one pair key-value: "order":"shoes"
document 2: Id is "2", data is a 3-pair key-value: "order":"shoes", "package":"big", "country":"Norway"
In this "Getting Started" says because it is so much easier to work with your own domain classes this quick-start will assume that you are going to do that. suggests make our own class like:
public class Entity
{
public ObjectId Id { get; set; }
public string Name { get; set; }
}
then use it like:
var entity = new Entity { Name = "Tom" };
...
entity.Name = "Dick";
collection.Save(entity);
Well, it defeats the idea of no-fixed columns, right?
So, I guess BsonDocument is the the model to use and is there any good samples for beginners?
I'm amazed how often this topic comes up... Essentially, this is more of a 'statically typed language limitation' than a MongoDB issue:
Schemaless doesn't mean you don't have any schema per se, it basically means you don't have to tell the database up front what you're going to store. It's basically "code first" - the code just writes to the database like it would to RAM, with all the flexibility involved.
Of course, the typical application will have some sort of reoccurring data structure, some classes, some object-oriented paradigm in one way or another. That is also true for the indexes: indexes are (usually) 'static' in the sense that you do have to tell mongodb about which field to index up front.
However, there is also the use case where you don't know what to store. If your data is really that unforeseeable, it makes sense to think "code first": what would you do in C#? Would you use the BsonDocument? Probably not. Maybe an embedded Dictionary does the trick, e.g.
public class Product {
public ObjectId Id {get;set;}
public decimal Price {get;set;}
public Dictionary<string, string> Attributes {get;set;}
// ...
}
This solution can also work with multikeys to simulate a large number of indexes to make queries on the attributes reasonably fast (though the lack of static typing makes range queries tricky). See
It really depends on your needs. If you want to have nested objects and static typing, things get a lot more complicated than this. Then again, the consumer of such a data structure (i.e. the frontend or client application) often needs to make assumptions that make it easy to digest this information, so it's often not possible to make this type safe anyway.
Other options include indeed using the BsonDocument, which I find too invasive in the sense that you make your business models depend on the database driver implementation; or using a common base class like ProductAttributes that can be extended by classes such as ProductAttributesShoes, etc. This question really revolves around the whole system design - do you know the properties at compile time? Do you have dropdowns for the property values in your frontend? Where do they come from?
If you want something reusable and flexible, you could simply use a JSON library, serialize the object to string and store that to the database. In any case, the interaction with such objects will be ugly from the C# side because they're not statically typed.

OOP - two tables into the same object

I have two tables in the database that are used almost for the same thing, but the tables don't have exactly the same structure.
Lets say I have one table for manual requests and another table for automatic requests. I have to load both tables into the same GridView and I'm using custom business objects.
To illustrate the question I'll call TManualReqTable and TAutomaticReqTable.
TManualReqTable
- ID
- Field1
- Field2
- Field3
- Field4
and
TAutomaticReqTable
- ID
- Field1
- Field3
In the code, I'm using the same object for these two tables. I have an interface with all the properties of both tables and I'm checking if the field exists when I'm loading the data to the object.
But I'm thinking this should be created with two objects and one superclass with abstracts methods.
What is your opinion about it?
I would create an interface IRequest that describes the fields & methods common to both, and then interfaces & classes for ManualRequest and AutomaticRequest that implement IRequest and also add the methods/fields unique to each of them.
You can use IRequest as the type for something that incorporates either one. When iterating through something that can include data from either, you can check whether each object implements the interfaces:
foreach (IRequest obj in RequestList) {
// do stuff that uses the common interface
if (obj is IManualRequest) {
// do stuff specific to manual requests
} else if (obj is IAutomaticRequest) {
// likewise
}
}
I follow a general rule to avoid creating base classes unless:
I've already designed or discovered sufficient commonality to give sufficient substance to the base class.
I have a use case for consuming the classes as the base class; if I don't have anything that can operate on the common functionality of the classes, there's little value in having a base class (can achieve the same functionality through composition of a class implementing the common behaviors.)
The requirements are sufficiently stable that I believe the base class abstraction will hold without significant modification in the future. Base classes become increasingly difficult to modify over time.
IMO, forget how the database looks like for a minute or two.
Think of how it should be structured as an object.
Think of how you would like to use that object. If you need to visualize, write some code of that yet non-existing object and tweak it until it looks elegant.
Think of how to make it happen.
model first development
Hope it helps.
well, there are a few assumptions i'm making here, so let me make them explicit...
given:
this is primarily a difference in query/display logic
the display logic can already handle the nulls
the underlying object being represented is the same between the two items
there's a simple way of determining whether this was a 'manual' or an 'automatic' call
i would say that inheritance is not the way i would model it. why? because it's the same object, not two different kinds of object. you're basically just not displaying a couple of the fields, and therefore do not need to query them.
so, i would probably try to accomplish something that makes clear the nature of the difference between the two (keep in mind that i intend this to show a way of organizing it so that it's clear, any particular implementation might have different needs; the main idea to glean is treating the differences as what they are: differences in what gets queried based upon some sort of condition.
public enum EQueryMode
{
Manual,
Automatic
}
public class FieldSpecification
{
public string FieldName { get; set; }
public bool[] QueryInMode { get; set; }
public FieldSpecification
(
string parFieldName,
bool parQueryInManual,
bool parQueryInAutomatic
)
{
FieldName = parFieldName;
QueryInMode = new bool[] { parQueryInManual, parQueryInAutomatic };
}
}
public class SomeKindOfRecord
{
public List<FieldSpecification> FieldInfo =
new List<FieldSpecification>()
{
new FieldSpecification("Field1", true, true),
new FieldSpecification("Field2", true, false),
new FieldSpecification("Field3", true, true),
new FieldSpecification("Field4", true, false)
};
// ...
public void PerformQuery(EQueryMode QueryMode)
{
List<string> FieldsToSelect =
(
from f
in FieldInfo
where
f.QueryInMode[(int)QueryMode]
select
f.FieldName
)
.ToList();
Fetch(FieldsToSelect);
}
private void Fetch(List<string> Fields)
{
// SQL (or whatever) here
}
}
edit: wow i can't seem to make a post today without having to correct my grammar! ;)

Mapping a List<string> to a delimited string with Fluent NHibernate

My model looks something like this:
public class Product
{
public string Name {get; set;}
public string Description {get; set;}
public double Price {get; set;}
public List<string> Features {get; set;}
}
I want my database table to be flat - the List should be stored as a delimited string:
Feature one|Feature two|Feature three for example.
When retrieved from the db, it should place each of those items back into a List
Is this possible?
I'm doing the very same in my current project, only I'm persisting a collection of enums as pipe-delimited numbers. It works the same way.
public class Product
{
protected string _features; //this is where we'll store the pipe-delimited string
public List<string> Features {
get
{
if(string.IsNullOrEmpty(_features)
return new List<String>();
return _features.Split(new[]{"|"}, StringSplitOptions.None).ToList();
}
set
{
_features = string.Join("|",value);
}
}
}
public class ProductMapping : ClassMap<Product>
{
protected ProductMapping()
{
Map(x => x.Features).CustomType(typeof(string)).Access.CamelCaseField(Prefix.Underscore);
}
}
I implemented something similar for the MySql set data type, which is a comma separated list in the db but a list of strings in the entity model. It involved using a custom data type in NHibernate, based on the PrimitiveType class. You wire this in using the mappings and the .CustomType< CustomType >( ) method on a map.
If you want I can send you a code snipet for the custom class.
I also implemented something similar for a Point3D struct. As cdmdotnet said you basically want to implement and IUserType that will pack/unpack Features into a single string via the NullSafeSet/NullSafeGet methods.
You may also need to implement the Equals() method, which is a little subtle. The reason why is best illustrated by an example:
Product p = session.Load(...);
p.Features.Add("extra feature");
session.Save(p);
The thing is, NHibernate upon hydration stores a reference to p.Features, and compares it to the value of p.Features upon a save request. For immutable property types this is fine, but in the above example, these references are identical, so the effective comparison is
var x = p.Features;
var changed = Equals(x, x);
Obviously a standard implementation of this will always return false.
How should one deal with this? I have no idea what the best practice is, but solutions are:
Make IUserType.Equals(object x, object y) always return false. This will force the packed string to be rebuilt and a database call to be made every single time the Product is saved, irregardless of whether Product has been semantically changed or not. Whether or not this is an issue depends on any number of factors (size/count of Feature objects, whether Product objects are saved when not changed, how many Product objects you have etc).
Make Features an IList and implement a ChangeAwareList<T> : IList<T> which is able to track changes (or keep a copy of its original) aware. Implement IUserType.Equals(object x, object y) to check if x/y are ChangeAwareList and implement the necessary logic to see if the list really has changed. This is the solution I went with in the end.
Maybe you could reuse code from the NHibernate GenericListType type. At the time I implemented the previous solution I didn't have enough experience to have a go at this.
If you have some prior experience with NHibernate I hope this should help get you started. If not let me know and I will try and put together a more verbose solution.

Is it ok to use C# Property like this

One of my fellow developer has a code similar to the following snippet
class Data
{
public string Prop1
{
get
{
// return the value stored in the database via a query
}
set
{
// Save the data to local variable
}
}
public void SaveData()
{
// Write all the properties to a file
}
}
class Program
{
public void SaveData()
{
Data d = new Data();
// Fetch the information from database and fill the local variable
d.Prop1 = d.Prop1;
d.SaveData();
}
}
Here the Data class properties fetch the information from DB dynamically. When there is a need to save the Data to a file the developer creates an instance and fills the property using self assignment. Then finally calls a save. I tried arguing that the usage of property is not correct. But he is not convinced.
This are his points
There are nearly 20 such properties.
Fetching all the information is not required except for saving.
Instead of self assignment writing an utility method to fetch all will have same duplicate code in the properties.
Is this usage correct?
I don't think that another developer who will work with the same code will be happy to see :
d.Prop1 = d.Prop1;
Personally I would never do that.
Also it is not the best idea to use property to load data from DB.
I would have method which will load data from DB to local variable and then you can get that data using property. Also get/set logically must work with the same data. It is strange to use get for getting data from DB but to use set to work with local variable.
Properties should really be as lightweight as possible.
When other developers are using properties, they expect them to be intrinsic parts of the object (that is, already loaded and in memory).
The real issue here is that of symmetry - the property get and set should mirror each other, and they don't. This is against what most developers would normally expect.
Having the property load up from database is not recommended - normally one would populate the class via a specific method.
This is pretty terrible, imo.
Properties are supposed to be quick / easy to access; if there's really heavy stuff going on behind a property it should probably be a method instead.
Having two utterly different things going on behind the same property's getter and setter is very confusing. d.Prop1 = d.Prop1 looks like a meaningless self-assignment, not a "Load data from DB" call.
Even if you do have to load twenty different things from a database, doing it this way forces it to be twenty different DB trips; are you sure multiple properties can't be fetched in a single call? That would likely be much better, performance-wise.
"Correct" is often in the eye of the beholder. It also depends how far or how brilliant you want your design to be. I'd never go for the design you describe, it'll become a maintenance nightmare to have the CRUD actions on the POCOs.
Your main issue is the absense of separations of concerns. I.e., The data-object is also responsible for storing and retrieving (actions that need to be defined only once in the whole system). As a result, you end up with duplicated, bloated and unmaintainable code that may quickly become real slow (try a LINQ query with a join on the gettor).
A common scenario with databases is to use small entity classes that only contain the properties, nothing more. A DAO layer takes care of retrieving and filling these POCOs with data from the database and defined the CRUD actions only ones (through some generics). I'd suggest NHibernate for the ORM mapping. The basic principle explained here works with other ORM mappers too and is explained here.
The reasons, esp. nr 1, should be a main candidate for refactoring this into something more maintainable. Duplicated code and logic, when encountered, should be reconsidered strongly. If the gettor above is really getting the database data (I hope I misunderstand that), get rid of it as quickly as you can.
Overly simplified example of separations of concerns:
class Data
{
public string Prop1 {get; set;}
public string Prop2 {get; set;}
}
class Dao<T>
{
SaveEntity<T>(T data)
{
// use reflection for saving your properies (this is what any ORM does for you)
}
IList<T> GetAll<T>()
{
// use reflection to retrieve all data of this type (again, ORM does this for you)
}
}
// usage:
Dao<Data> myDao = new Dao<Data>();
List<Data> allData = myDao.GetAll();
// modify, query etc using Dao, lazy evaluation and caching is done by the ORM for performance
// but more importantly, this design keeps your code clean, readable and maintainable.
EDIT:
One question you should ask your co-worker: what happens if you have many Data (rows in database), or when a property is a result of a joined query (foreign key table). Have a look at Fluent NHibernate if you want a smooth transition from one situation (unmaintainable) to another (maintainable) that's easy enough to understand by anybody.
If I were you I would write a serialize / deserialize function, then provide properties as lightweight wrappers around the in-memory results.
Take a look at the ISerialization interface: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx
This would be very hard to work with,
If you set the Prop1, and then get Prop1, you could end up with different results
eg:
//set Prop1 to "abc"
d.Prop1 = "abc";
//if the data source holds "xyz" for Prop1
string myString = d.Prop1;
//myString will equal "xyz"
reading the code without the comment you would expect mystring to equal "abc" not "xyz", this could be confusing.
This would make working with the properties very difficult and require a save every time you change a property for it to work.
As well as agreeing with what everyone else has said on this example, what happens if there are other fields in the Data class? i.e. Prop2, Prop3 etc, do they all go back to the database, each time they are accessed in order to "return the value stored in the database via a query". 10 properties would equal 10 database hits. Setting 10 properties, 10 writes to the database. That's not going to scale.
In my opinion, that's an awful design. Using a property getter to do some "magic" stuff makes the system awkward to maintain. If I would join your team, how should I know that magic behind those properties?
Create a separate method that is called as it behaves.

When to use Properties and Methods?

I'm new to the .NET world having come from C++ and I'm trying to better understand properties. I noticed in the .NET framework Microsoft uses properties all over the place. Is there an advantage for using properties rather than creating get/set methods? Is there a general guideline (as well as naming convention) for when one should use properties?
It is pure syntactic sugar. On the back end, it is compiled into plain get and set methods.
Use it because of convention, and that it looks nicer.
Some guidelines are that when it has a high risk of throwing Exceptions or going wrong, don't use properties but explicit getters/setters. But generally even then they are used.
Properties are get/set methods; simply, it formalises them into a single concept (for read and write), allowing (for example) metadata against the property, rather than individual members. For example:
[XmlAttribute("foo")]
public string Name {get;set;}
This is a get/set pair of methods, but the additional metadata applies to both. It also, IMO, simply makes it easier to use:
someObj.Name = "Fred"; // clearly a "set"
DateTime dob = someObj.DateOfBirth; // clearly a "get"
We haven't duplicated the fact that we're doing a get/set.
Another nice thing is that it allows simple two-way data-binding against the property ("Name" above), without relying on any magic patterns (except those guaranteed by the compiler).
There is an entire book dedicated to answering these sorts of questions: Framework Design Guidelines from Addison-Wesley. See section 5.1.3 for advice on when to choose a property vs a method.
Much of the content of this book is available on MSDN as well, but I find it handy to have it on my desk.
Consider reading Choosing Between Properties and Methods. It has a lot of information on .NET design guidelines.
properties are get/set methods
Properties are set and get methods as people around here have explained, but the idea of having them is making those methods the only ones playing with the private values (for instance, to handle validations).
The whole other logic should be done against the properties, but it's always easier mentally to work with something you can handle as a value on the left and right side of operations (properties) and not having to even think it is a method.
I personally think that's the main idea behind properties.
I always think that properties are the nouns of a class, where as methods are the verbs...
First of all, the naming convention is: use PascalCase for the property name, just like with methods. Also, properties should not contain very complex operations. These should be done kept in methods.
In OOP, you would describe an object as having attributes and functionality. You do that when designing a class. Consider designing a car. Examples for functionality could be the ability to move somewhere or activate the wipers. Within your class, these would be methods. An attribute would be the number of passengers within the car at a given moment. Without properties, you would have two ways to implement the attribute:
Make a variable public:
// class Car
public int passengerCount = 4;
// calling code
int count = myCar.passengerCount;
This has several problems. First of all, it is not really an attribute of the vehicle. You have to update the value from inside the Car class to have it represent the vehicles true state. Second, the variable is public and could also be written to.
The second variant is one widley used, e. g. in Java, where you do not have properties like in c#:
Use a method to encapsulate the value and maybe perform a few operations first.
// class Car
public int GetPassengerCount()
{
// perform some operation
int result = CountAllPassengers();
// return the result
return result;
}
// calling code
int count = myCar.GetPassengerCount();
This way you manage to get around the problems with a public variable. By asking for the number of passengers, you can be sure to get the most recent result since you recount before answering. Also, you cannot change the value since the method does not allow it. The problem is, though, that you actually wanted the amount of passengers to be an attribute, not a function of your car.
The second approach is not necessarily wrong, it just does not read quite right. That's why some languages include ways of making attributes look like variables, even though they work like methods behind the scenes. Actionscript for example also includes syntax to define methods that will be accessed in a variable-style from within the calling code.
Keep in mind that this also brings responsibility. The calling user will expect it to behave like an attribute, not a function. so if just asking a car how many passengers it has takes 20 seconds to load, then you probably should pack that in a real method, since the caller will expect functions to take longer than accessing an attribute.
EDIT:
I almost forgot to mention this: The ability to actually perform certain checks before letting a variable be set. By just using a public variable, you could basically write anything into it. The setter method or property give you a chance to check it before actually saving it.
Properties simply save you some time from writing the boilerplate that goes along with get/set methods.
That being said, a lot of .NET stuff handles properties differently- for example, a Grid will automatically display properties but won't display a function that does the equivalent.
This is handy, because you can make get/set methods for things that you don't want displayed, and properties for those you do want displayed.
The compiler actually emits get_MyProperty and set_MyProperty methods for each property you define.
Although it is not a hard and fast rule and, as others have pointed out, Properties are implemented as Get/Set pairs 'behind the scenes' - typically Properties surface encapsulated/protected state data whereas Methods (aka Procedures or Functions) do work and yield the result of that work.
As such Methods will take often arguments that they might merely consume but also may return in an altered state or may produce a new object or value as a result of the work done.
Generally speaking - if you need a way of controlling access to data or state then Properties allow the implementation that access in a defined, validatable and optimised way (allowing access restriction, range & error-checking, creation of backing-store on demand and a way of avoiding redundant setting calls).
In contrast, methods transform state and give rise to new values internally and externally without necessarily repeatable results.
Certainly if you find yourself writing procedural or transformative code in a property, you are probably really writing a method.
Also note that properties are available via reflection. While methods are, too, properties represent "something interesting" about the object. If you are trying to display a grid of properties of an object-- say, something like the Visual Studio form designer-- then you can use reflection to query the properties of a class, iterate through each property, and interrogate the object for its value.
Think of it this way, Properties encapsulate your fields (commoningly marked private) while at the same time provides your fellow developers to either set or get the field value. You can even perform routine validation in the property's set method should you desire.
Properties are not just syntactic sugar - they are important if you need to create object-relational mappings (Linq2Sql or Linq2Entities), because they behave just like variables while it is possible to hide the implementation details of the object-relational mapping (persistance). It is also possible to validate a value being assigned to it in the getter of the property and protect it against assigning unwanted values.
You can't do this with the same elegance with methods. I think it is best to demonstrate this with a practical example.
In one of his articles, Scott Gu creates classes which are mapped to the Northwind database using the "code first" approach. One short example taken from Scott's blog (with a little modification, the full article can be read at Scott Gu's blog here):
public class Product
{
[Key]
public int ProductID { get; set; }
public string ProductName { get; set; }
public Decimal? UnitPrice { get; set; }
public bool Discontinued { get; set; }
public virtual Category category { get; set; }
}
// class Category omitted in this example
public class Northwind : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
You can use entity sets Products, Categories and the related classes Product and Category just as if they were normal objects containing variables: You can read and write them and they behave just like normal variables. But you can also use them in Linq queries, persist them (store them in the database and retrieve them).
Note also how easy it is to use annotations (C# attributes) to define the primary key (in this example ProductID is the primary key for Product).
While the properties are used to define a representation of the data stored in the database, there are some methods defined in the entity set class which control the persistence: For example, the method Remove() marks a given entity as deleted, while Add() adds a given entity, SaveChanges() makes the changes permanent. You can consider the methods as actions (i.e. you control what you want to do with the data).
Finally I give you an example how naturally you can use those classes:
// instantiate the database as object
var nw = new NorthWind();
// select product
var product = nw.Products.Single(p => p.ProductName == "Chai");
// 1. modify the price
product.UnitPrice = 2.33M;
// 2. store a new category
var c = new Category();
c.Category = "Example category";
c.Description = "Show how to persist data";
nw.Categories.Add(c);
// Save changes (1. and 2.) to the Northwind database
nw.SaveChanges();

Categories

Resources