Function overload in c# best practices - c#

I'm essentially a VB.Net programmer who's having to do a small side-project in c#, so please forgive me if this is an obvious question!
I am using a third party API that returns data in array, for which I have to interrogate the datatype before obtaining the data, and then pass to the API an array of the correct data type in order for the data to be packed correctly: e.g.
// Get info
Int32 dataLength = MyAPI.GetDataLength();
Int32 dataDepth = MyAPI.GetDataDepth();
//And get the data.
switch (dataDepth)
{
case 8:
byte[] bData = new byte[dataLength];
MyAPI.GetData(bData);
//Do Work
WorkFunction(bData);
break;
case 16:
Int16[] iData = new Int16[dataLength];
MyAPI.GetData(iData);
//Do Work
WorkFunction(iData);
break;
}
This works fine, and correctly populates either the byte array, or the Int16 array. At the moment, I have an overload for WorkFunction as follows:
void WorkFunction(byte[] data){
//Do Stuff
}
void WorkFunction(Int16[] data){
//Do Stuff
}
This is fine, and all works OK - but the work performed in WorkFunction is essentially the same (displaying text/graphing data) and having what is essentially a copy-and-paste of code in two functions can't be great practice?
I realise I could just have the Int16[] version of WorkFunction and convert
int[] bytesAsInts = yourBytes.Select(x => (int)x).ToArray();
but the data is being fed in from a hardware device, and I am reluctant to put in additional "work" unless it's actually required.
What would you consider is "best practice" ??
Thanks.
Thanks for comments so far. WorkFunction is pretty simple. It's updating a few
labels, and plotting some points on a graph. There are a couple of extra parameters, but these are of fixed data type:
void WorkFunction(Int16[] data, double aValue){
//Do Stuff
MyTextBox.text = aValue.ToString("0.00");
MyChartSeries.Points.Clear();
for (int i = 0; i < data.Length; i++) {
MyChartSeries.Points.AddXY(i, data[i]); }
}

I would use generics as explained in the comments, but I think you need an answer in order to close your question.
void WorkFunction<DType>(DType[] data, double aValue){
//Do Stuff
MyTextBox.text = aValue.ToString("0.00");
MyChartSeries.Points.Clear();
for (int i = 0; i < data.Length; i++) {
MyChartSeries.Points.AddXY(i, data[i]); }
}
Generics will do the job for you.
If you want to know more about generics maybe with a more familiar language, check this.
Then if the implementation doesn't fit the purpose, please tell us more about the usage of data.

Overloading is good practice when functionality is same in c#.net. but recently few years/months there are also come with new features like generic method which will allow creating single method with generic arguments. so you have the option not to create overloading but create the generic function which will allow all dataype in just single function
example:
void WorkFunction<Datatype>(Datatype[] data, double aValue){
//Do Stuff
MyTextBox.text = aValue.ToString("0.00");
MyChartSeries.Points.Clear();
for (int i = 0; i < data.Length; i++) {
MyChartSeries.Points.AddXY(i, data[i]);
}
}

One option i often use because of it's simplicity is to put "identical code" inside a separate function :
void WorkFunction(byte[] data){
int[] bytesAsInts = data.Select(x => (int)x).ToArray();
DoStuff(bytesAsInts);
}
void WorkFunction(Int16[] data){
DoStuff(data);
}
public void DoStuff(int16[] dataFromBoth)
{
// here is where you do stuff, whatever it came from.
}
It's basically code extracting, there is even some tools that can do it for you accurately.

Related

Best practice/way to serialize the object using c#

im working on collaborative drawing (socket-programming) in which i have to send and recieve 100 to 1000 Point of C# Class, so i wanted to know that what is the best way to send and recieve these points.. i have two options.. one is List<Point> and other is Point[] using either BinaryFormatter or JSON, but i have read that JSON is used to send small amount of data, and i dont know will it work with C# window applications or not
thanx for any help
There are so many ways to serialize your data.
If you want to transfer a lot of objects, don't use JSON - it's a text format, every unnecessary character is a byte waste of space. If your object uses, say, 20 bytes, and it's textual representation uses 100 bytes (e.g. because of the field names) than it's a bad choice for large collections, especially with network transfer.
Unless you need the serialized output to be readable, of course. That's, I believe, the only reason to use JSON.
Binary serialization is totally a different matter. There are many serializers out there: BinaryFormatter, protobuf-net by Marc Gravell, Migrant (which I co-author), many many others.
The choice is hard and domain-specific. Do you need graph dependency preserved? Do you have many different objects or large collections? Different libraries will give you different results.
As your data set is not very big (I assume we're talking about a small class/struct Point), I'd focus on readability. You don't want to design your code to be easily serializable, and you seldom want to write wrappers (because they have to be maintained).
Use datatypes that are meaningful in your context.
Do you need random access to your Points? Then probably you need an array. Do you need to create a resizable collection and iterate over it? List might be better.
I've ran a simple test, using 1000000 System.Windows.Point instances, both on BinaryFormatter and Migrant. There was no real difference whether I've used Point[] or List<Point>.
The choice is yours.
Here is a snippet of the test I've done. The code is not very pimped-up, but you'll change it to List<Point> with no effort. If you need a simple framework to serialize data, I may recommend Migrant. Please notice the one-liner usage: result = Serializer.DeepClone (source); ;-)
using System;
using Antmicro.Migrant;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Windows;
namespace test15
{
class MainClass
{
private static void EnsureEqual(Point[] source, Point[] result)
{
for (var i = 0; i < result.Length; ++i) {
if (source [i] != result [i]) {
throw new Exception ();
}
}
}
public static void Main (string[] args)
{
var source = new Point[1000000];
Point[] result, binResult;
var timer = new Stopwatch ();
for (var i = 0; i < source.Length; ++i) {
source [i] = new Point (i, i);
}
//Migrant
timer.Start ();
result = Serializer.DeepClone (source);
timer.Stop ();
EnsureEqual (source, result);
Console.WriteLine ("Migrant time: {0}", timer.Elapsed);
timer.Reset ();
//Binary formatter
var binaryForm = new BinaryFormatter ();
using (var ms = new MemoryStream ()) {
timer.Start ();
binaryForm.Serialize (ms, source);
ms.Position = 0;
binResult = binaryForm.Deserialize(ms) as Point[];
timer.Stop ();
}
Console.WriteLine ("Binary formatter time: {0}", timer.Elapsed);
EnsureEqual (source, binResult);
}
}
}

C# function not accepting CLI array in C++

I'm currently writing a program in CLI/C++ using an imported C# package. I need to use one of the functions in one of the C# objects which takes in an array. Unfortunately it isn't allowing me to use a CLI array, defined like so:
array<float>^ knots = gcnew array<float>(nurbs->GetNumKnots());
(and then populated in a loop).
The object and the function are:
TRH::NURBSCurveKit^ nurbsKit = gcnew TRH::NURBSCurveKit();
nurbsKit->SetKnots(nurbs->GetNumKnots(), knots);
This returns an error basically saying that the cli::array type isn't compatible. Does anyone know of a way where I can cast the array, or possibly define it differently?
I'm quite new to CLI so I'm a little vague on the way it handles things at times.
Thanks
(I do something similar later on using an array of TRH::Points, but they're not defined as references or pointers, so I'm not sure if they'd work with any solutions or not).
I'm not sure if it's the same NURBSCurveKit, but according to an online API reference I found, the SetKnots method takes one parameter, not two. Since a managed array knows how long it is, you generally don't have to pass in a length with an array.
If this matches your API, just switch to pass a single parameter to SetKnots. (The reference I found uses a different namespace, so it may not be what you're using.)
array<float>^ knots = gcnew array<float>(nurbs->GetNumKnots());
TRH::NURBSCurveKit^ nurbsKit = gcnew TRH::NURBSCurveKit();
nurbsKit->SetKnots(knots);
This is my test case, seems everything is fine.
C#
namespace CS
{
public class Test
{
public int GetNum()
{
return 5;
}
public void ShowArray(int num, float[] arr)
{
for (int i = 0; i < num; i++)
{
Console.WriteLine("[{0}] = {1}",i,arr[i]);
}
}
}
}
C++/CLI
using namespace System;
using namespace CS;
int main(array<System::String ^> ^args)
{
Test^ test = gcnew Test();
array<float>^ arr = gcnew array<float>(test->GetNum());
for (int i = 0; i < test->GetNum(); i ++)
{
arr[i] = (float)i * i;
}
test->ShowArray(test->GetNum(), arr);
Console::ReadKey();
return 0;
}
Dose you code have something different form mine?

should i try to avoid "new" keyword in ultra-low-latency software?

I'm writing HFT trading software. I do care about every single microsecond. Now it written on C# but i will migrate to C++ soon.
Let's consider such code
// Original
class Foo {
....
// method is called from one thread only so no need to be thread-safe
public void FrequentlyCalledMethod() {
var actions = new List<Action>();
for (int i = 0; i < 10; i++) {
actions.Add(new Action(....));
}
// use actions, synchronous
executor.Execute(actions);
// now actions can be deleted
}
I guess that ultra-low latency software should not use "new" keyword too much, so I moved actions to be a field:
// Version 1
class Foo {
....
private List<Action> actions = new List<Action>();
// method is called from one thread only so no need to be thread-safe
public void FrequentlyCalledMethod() {
actions.Clear()
for (int i = 0; i < 10; i++) {
actions.Add(new Action { type = ActionType.AddOrder; price = 100 + i; });
}
// use actions, synchronous
executor.Execute(actions);
// now actions can be deleted
}
And probably I should try to avoid "new" keyword at all? I can use some "pool" of pre-allocated objects:
// Version 2
class Foo {
....
private List<Action> actions = new List<Action>();
private Action[] actionPool = new Action[10];
// method is called from one thread only so no need to be thread-safe
public void FrequentlyCalledMethod() {
actions.Clear()
for (int i = 0; i < 10; i++) {
var action = actionsPool[i];
action.type = ActionType.AddOrder;
action.price = 100 + i;
actions.Add(action);
}
// use actions, synchronous
executor.Execute(actions);
// now actions can be deleted
}
How far should I go?
How important to avoid new?
Will I win anything while using preallocated object which I only need to configure? (set type and price in example above)
Please note that this is ultra-low latency so let's assume that performance is preferred against readability maintainability etc. etc.
In C++ you don't need new to create an object that has limited scope.
void FrequentlyCalledMethod()
{
std::vector<Action> actions;
actions.reserve( 10 );
for (int i = 0; i < 10; i++)
{
actions.push_back( Action(....) );
}
// use actions, synchronous
executor.Execute(actions);
// now actions can be deleted
}
If Action is a base class and the actual types you have are of a derived class, you will need a pointer or smart pointer and new here. But no need if Action is a concrete type and all the elements will be of this type, and if this type is default-constructible, copyable and assignable.
In general though, it is highly unlikely that your performance benefits will come from not using new. It is just good practice here in C++ to use local function scope when that is the scope of your object. This is because in C++ you have to take more care of resource management, and that is done with a technique known as "RAII" - which essentially means taking care of how a resource will be deleted (through a destructor of an object) at the point of allocation.
High performance is more likely to come about through:
proper use of algorithms
proper parallel-processing and synchronisation techniques
effective caching and lazy evaluation.
As much as I detest HFT, I'm going to tell you how to get maximum performance out of each thread on a given piece of iron.
Here's an explanation of an example where a program as originally written was made 730 times faster.
You do it in stages. At each stage, you find something that takes a good percentage of time, and you fix it.
The keyword is find, as opposed to guess.
Too many people just eyeball the code, and fix what they think will help, and often but not always it does help, some.
That's guesswork.
To get real speedup, you need to find all the problems, not just the few you can guess.
If your program is doing new, then chances are at some point that will be what you need to fix.
But it's not the only thing.
Here's the theory behind it.
For high-performance trading engines at good HFT shops, avoiding new/malloc in C++ code is a basic.

#define - Migrating C++ to C# or VB.Net

I need some advice on how to do the following in either C# and VB.net.
In C++, in my header file I do the following:
#define StartButtonPressed Input[0]==1 // Input is an array declared in .cpp file
In my .cpp file, i have a code something like this:
if(StartButtonPressed)
// do something
The reason of me doing so is so that my code is easier to read.
I tried the same thing in C# but it got error. How could I do the same thing in C# and VB.Net?
Please advice. Thanks.
There is no good reason to use a macro for this in C++; you could just as easily make it a function and the code would be far cleaner:
bool IsStartButtonPressed()
{
return Input[0] == 1;
}
Input should also probably be passed as an argument to the function, but it's hard to tell exactly where that is coming from.
You're best off creating a property in your class
protected bool StartButtonPressed {
get { return Input[0] == 1; }
}
then your code can be as before
.
.
.
if(StartButtonPressed) {
.
.
.
}
However for consistency with the .net framework I'd suggest calling the property IsStartButtonPressed
If you need to to be evaluated at the point of the if statement then you really need a function or a property. However is this is one time evaluation you can use a field
bool isStartButtonPressed = Input[0] ==1;
If you want may classes to have this functionality then I'd recommend a static function from another class, something like
public static class ButtonChecker {
public static bool IsPressed(int[] input) {
return input[0] == 1;
}
}
Then you call it anywhere with
if(ButtonChecker.IsPressed(Input)) {
.
.
}
But ultimately you cannot use macro's like you're used in C/C++. You shouldn't be worried about performance of properties and functions like this as the CLR jit compiler implementation is very very good for them
Here is an example program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace ConsoleApplication1 {
public static class ButtonChecker {
public static bool IsPressed(int[] input) {
return input[0] == 1;
}
}
static class Program {
public static void Main(){
int[] Input = new int[6] { 1, 0, 2, 3,4 , 1 };
for(int i = 0; i < Input.Length; ++i){
Console.WriteLine("{0} Is Pressed = {1}", i, ButtonChecker.IsPressed(Input));
}
Console.ReadKey();
}
}
}
You could use an enum
public enum buttonCode
{
startButton = 0,
stopButton = 1
// more button definitions
}
Then maybe one function
public bool IsButtonPressed(b as buttoncode)
{
return Input[b] == 1;
}
Then your calls look like:
if IsButtonPressed(buttonCode.StartButton) { }
The only changes needed to switch button codes are then in the enum, not spread across multiple functions.
Edited to Add:
If you want individually named functions, you could do this:
public bool IsStartButtonPressed()
{
return Input[buttonCode.StartButton] == 1;
}
Still, all of the edits would be in the enum, not the functions.
Bjarne Stroustrup wrote:
The first rule about macros is: Do not use them if you do not have to. Almost every macro demonstrates a flaw in the programming language, in the program, or in the programmer.
It's worth noting two things here before saying anything else. The first is that "macro" can mean a very different thing in some other languages; one would not make the same statement about Lisp. the second is that Stroustrup is willing to take his share of the blame in saying that one reason for using macros is "a flaw in the programming language", so it's not like he's just being superior in condemning their use.
This case though isn't a flaw in the programming language, except that the language lets you do it in the first place (but has to, to allow other macros). The only purpose of this macro is to make the code harder to read. Just get rid of it. Replace it with some actual C# code like:
private bool StartButtonPressed
{
get
{
return Input[0]==1
}
}
Edit:
Seeing the comment above about wanting to be faster to code, I would do something like:
private enum Buttons
{
Start = 0,
Stop = 1,
Pause = 2,
/* ... */
}
private bool IsPressed(Buttons button)
{
return Input[(int)button] == 1;
}
And then call e.g. IsPressed(Buttons.Start). Then I'd fix the C++ to use the same approach too (in C++ I would even be able to leave out the Buttons. where I wanting particularly great concision).

Is there a way to add an Extension Method to a Lambda?

In this example I want to add a .loop({quantity},{sleepvalue}) to a method
I got it to work with this:
this.loop(count, 500,
()=>{
var image = Screenshots.getScreenshotOfDesktop();
pictureBox.load(image);
images.Add(image);
updateTrackBar();
});
using this extension method:
public static void loop(this Object _object, int count, int delay, MethodInvoker methodInvoker)
{
for(int i=0; i < count; i++)
{
methodInvoker();
_object.sleep(delay);
}
}
which means that the invocation syntax is:
this.loop(15,500, () => {...code...});
but ideally what I wanted to do was something like:
()=> { ...code...}.loop(10,500);
which doesn't work unless I do it like this:
new MethodInvoker(()=>{...code...}).loop(10,500);
which will work with this version of the extension method:
public static void loop(this MethodInvoker methodInvoker, int count, int delay)
{
for(int i=0; i < count; i++)
{
methodInvoker();
Processes.Sleep(delay);
}
}
No, unfortunately there isn't.
I blogged about this quite a while ago :(
However, with the right choice of indentation, you can make it look almost identical to a normal loop:
HelperType.Loop(count, 500, () =>
{
// Code here
});
That's what a lot of the Parallel Extensions samples look like
I wouldn't make it an extension method on something you're not actually going to use, just so that you can use "this" instead of the real type name... not unless you've got a real use for the object it's called "on", anyway.
(I'd also suggest following .NET naming conventions - make your methods PascalCase.)
I really advise not to try to do this.
It's often a bad idea, in my opinion, to implement extension methods on core types, such as a delegate/lambda type, or System.Object.
This just causes confusion. I see little advantage to your proposed syntax:
() => { ..code... }.Loop(10, 500);
To me, that is far less readable than:
Utilities.RepeatWithDelay(10, 500, () => {....code... } );

Categories