|
Can any one tell me best coding practises in c#?
|
|
|
|
|
MSDN is always great place to dig into C#.Net or any .Net compliant languages or technology. Thanks
|
|
|
|
|
There are different "practices" out there. You can use the SOLID principle, you can learn and follow design patterns or the practices of a technology like LINQ, WPF, WCF, ... (by reading the book and following the advice). Personally, I keep everything in an N-tier format (feel free to read my articles 1[^] and 2[^] on that topic) and I like to follow the K.I.S.S. principle and the golden rule of "if it's not broken, don't fix it" see my other article[^]).
The absolute most important rule you should always follow in programming : Stay consistent.
Be it in programming style, naming conventions, commenting style, design style, or whatever ...
Mostly you will not use "one best practice", but rather a mix of several things that just work for you.
Read up on all the key words and find your own way young padawan.
hope this helps.
|
|
|
|
|
|
sure....
modified 15-Apr-15 3:35am.
|
|
|
|
|
Also try to implement that in your day to day coding.
Then only you can understand practically.
Hope this will help you
|
|
|
|
|
Message Removed
modified 15-Apr-15 1:14am.
|
|
|
|
|
I want to know generic interface and generic delegates in simple terminology.In MSDN so many things are there but please clerar it in simple words
Gyan
|
|
|
|
|
Okay. Before covering what they are, let's establish the level you are at with regards to C# so that we don't assume you know something you don't. Do you know what generics are? Do you understand them?
|
|
|
|
|
Yes I know generic well as well as I know Interface and delegate well.
|
|
|
|
|
Okay so a generic interface is, at its most basic level, an interface that has a generic element to it. In other words, the signature of the interface means that it can be used for different types. Consider this interface:
public interface IPersist<T>
{
void LoadLayout(T instance);
void SaveLayout(T instance);
} Suppose we have a class that looks like this:
public class MyModel
{
public string Name { get; set; }
public string FriendlyName { get; set; }
public DateTime LastLogin { get; set; }
} Now, we want to write a class that performs the persistence for this class. Let's write it like this:
public class MyModelPersistence : IPersist<MyModel>
{
public void LoadLayout(MyModel instance)
{
}
public void SaveLayout(MyModel instance)
{
}
} A common use of generic interfaces is in providing the interface definitions for generic collections such as List<T> .
Now, where things get really interesting is when it comes to covariant and contravariant interfaces. I will direct you to the discussion here[^]. The discussion around the zoo is an excellent example of using co and contra variance.
Similar to a generic interface, a generic delegate is one that uses the generic parameter to create a strong type (basically, by giving it a Type, you remove the need to use object as the delegate type, thus removing the need to perform boxing/unboxing to get the value of the parameter).
|
|
|
|
|
I hate you yoda! that simple description of generic interfaces makes we want to revisit my data layer and see if it is a viable change to the approach I use now
otherwise +5 for a simple explination
Every day, thousands of innocent plants are killed by vegetarians.
Help end the violence EAT BACON
|
|
|
|
|
My way of doing things changed to thinking like this once I really got into SOLID as a discipline.
|
|
|
|
|
Pete O'Hanlon wrote: ... once I really got into SOLID as a discipline Hi Pete, Do you ever have flash-backs where you re-live being amorphous ? I know I do; soy-milk helps me with that. Maybe my problem is I am just too "at home" in amorphous.
I'm going to dare post an alternative take on generic interface on this thread based on your example, and I'd be very keen to have your feedback ... since I trust you more than I trust myself (with code).
I'm curious if you see any "inherent tension" between the "I" principle in SOLID: "many client-specific interfaces are better than one general-purpose interface" (Martin), and the use of generic interfaces. I do not claim to "grasp" the SOLID principles in depth, but I am trying to increase my understanding of them.
cheers, Bill
«To kill an error's as good a service, sometimes better than, establishing new truth or fact.» Charles Darwin in "Prospero's Precepts"
modified 14-Apr-15 13:42pm.
|
|
|
|
|
I loved being amorphous. Providing my own gaseous cloud was one of the joys of single life. BillWoodruff wrote: 'm going to dare post an alternative take on generic interface on this thread based on your example Go for it. My example is merely one way of doing this, based on typing in the editor.
|
|
|
|
|
Thanks Pete O'Hanlon for your simple explanation.
|
|
|
|
|
|
This is an "alternate take" on the code example using a generic interface provided on this thread by Pete O'Hanlon. It uses a pattern I've used before which is slightly different than the in Pete's example; of course I do not claim this is any "better" than Pete's example !
I've made sure this example actually works by testing it. 'DataContract/DataMember is used for serialization/de-serialization. I'd really appreciate any feedback on this code vis-a-vis its differences with Pete's implementation.
using System;
using System.IO;
using System.Runtime.Serialization;
namespace YourNameSpace
{
public interface IPersist<T> where T : class
{
void LoadLayout();
void SaveLayout();
}
[DataContract]
public class MyModel : IPersist<MyModel>
{
private readonly string FilePath;
public MyModel(string name, string fname, string filepath)
{
Name = name;
FriendlyName = fname;
FilePath = filepath;
LastLogin = DateTime.Now;
}
[DataMember]
public string Name { private set; get; }
[DataMember]
public string FriendlyName { private set; get; }
[DataMember]
public DateTime LastLogin { private set; get; }
public void LoadLayout()
{
if (!File.Exists(FilePath)) throw new FileNotFoundException("Invalid file path");
MyModel temp;
try
{
temp = Persistence<MyModel>.LoadLayout(FilePath);
}
catch (Exception ex)
{
throw new InvalidDataContractException(string.Format("Failed to read data file: {0}", ex.Message),
ex.InnerException);
}
if (temp == null) throw new InvalidDataContractException("no data error");
Name = temp.Name;
FriendlyName = temp.FriendlyName;
LastLogin = temp.LastLogin;
}
public void SaveLayout()
{
if (!File.Exists(FilePath)) throw new FileNotFoundException("Invalid file path");
try
{
Persistence<MyModel>.SaveLayout(FilePath, this);
}
catch (Exception ex)
{
throw new InvalidDataContractException(string.Format("Failed to save to data file: {0}", ex.Message),
ex.InnerException);
}
}
}
internal static class Persistence<T> where T : class
{
private static DataContractSerializer serializer;
public static T LoadLayout(string filepath)
{
serializer = new DataContractSerializer(typeof (T));
Console.WriteLine("Loading");
T LoadedData = null;
using (var reader = new FileStream(filepath, FileMode.Open, FileAccess.Read))
{
LoadedData = serializer.ReadObject(reader) as T;
}
return LoadedData;
}
public static void SaveLayout(string filepath, T instance)
{
serializer = new DataContractSerializer(typeof (T));
Console.WriteLine("Saving");
using (var writer = new FileStream(filepath, FileMode.Create, FileAccess.Write))
{
serializer.WriteObject(writer, instance);
}
}
}
}
«To kill an error's as good a service, sometimes better than, establishing new truth or fact.» Charles Darwin in "Prospero's Precepts"
modified 15-Apr-15 13:03pm.
|
|
|
|
|
You've added a generic type parameter to the IPersist<T> interface, but you don't seem to use it anywhere. You'd get the same result with a non-generic interface.
The serializer field on your Persistence<T> class should be a local variable in both methods. There's no need to expose it to the outside world, and your current implementation is not thread-safe.
You've also missed the set; (or the body of the get; ) on the FilePath auto-property.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hi Richard, thanks for your feedback !Richard Deeming wrote: You've added a generic type parameter ... but you don't seem to use it anywher "Yes" in the sense that IPersist could be defined without the generic parameter and still "work;" "no" in the sense that constraining IPersist using 'Where does require generic declaration.Richard Deeming wrote: serializer field ... should be a local variable in both methods. Spot on !Richard Deeming wrote: missed the set; (or the body of the get; ) on the FilePath auto-property. That syntax is certainly legal/compilable in .NET 4.5. An "automatic" property with only a 'getter is de facto readonly. If you think that's a code-smell, I'd be inclined to accept your view. There are those who believe strongly that all automatic properties are "suspect: [^].
At this point, I am not really sure my code example demonstrated the "true virtue" of a "generic interface," but I am very happy to get the chance to learn from you, Pete, and Eddy !
«To kill an error's as good a service, sometimes better than, establishing new truth or fact.» Charles Darwin in "Prospero's Precepts"
|
|
|
|
|
BillWoodruff wrote: That syntax is certainly legal/compilable in .NET 4.5. An "automatic" property with only a 'getter is de facto readonly.
Not in .NET 4.5 - did you mean C# 6 / .NET 4.6 / VS2015?
'FilePath.get' must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Okay ... should have known ... you are right !
I whipped up that sample code in VS 2015 CTP6, but it is compiled with FrameWork 4.5
No compile-time warning, no error message: it works !
I've checked to see if any warning potentially activated by ReSharper 9.1 is turned off, but that's not the case. I've got treat all warnings as errors turned on in VS' 'Build parameter options, and the highest level warning set (4), also.
So, there's a difference in compiler behavior in 2015 CTP 6 ? ... mmm ...
cheers, Bill
«To kill an error's as good a service, sometimes better than, establishing new truth or fact.» Charles Darwin in "Prospero's Precepts"
|
|
|
|
|
Hi Bill,
it's a C# 6.0 feature, readonly auto-properties. Like readonly fields, they can be initialized where they're declared or in the constructor. Here's a nice write-up from Jon Skeet: C# 6 in action[^]
Thank you guys for this interesting thread
cheers, Sascha
|
|
|
|
|
As well as the comments that Richard has made, the fact that MyModel is responsible for also loading MyModel from persistence violates single responsibility if we take the concept here that MyModel represents a data entity of some description. This is why I had the idea of the model separate to the item that's loading the model. One of the main reasons I like to do this is because this clear separation makes things a lot easier for me to test. I can simply mock an interface and do a test on the code that's calling IPersist... to verify that it has made the call (using a mocking framework).
|
|
|
|
|
Hi Pete, I am delighted to have feedback from you !Pete O'Hanlon wrote: the fact that MyModel is responsible for also loading MyModel from persistence violates single responsibility This may be semantic hair-splitting, but do you consider initializing, or "refreshing," the properties of an instance of 'MyModel from an external data file "loading" ?
One question about your code: while having an instance of 'MyModel seems logically required in the 'SaveLayout code, the fact your 'LoadLayout code method is a void-return method means that you would be ... I'm having trouble articulating here ... "refreshing" the field values of the passed-in instance rather than making use of a new instance of 'MyModel ? Sorry if that's unclear; it's now 5:32AM here after a long, sleepless, hot tropical night punctuated by the heavy-ordnance fireworks of Thais celebrating the five-day solar New Year rite-of-passage, Songkraan
I wish I had the background/depth to appreciate your comments on mocking and testing.
thanks, Bill
«To kill an error's as good a service, sometimes better than, establishing new truth or fact.» Charles Darwin in "Prospero's Precepts"
|
|
|
|