How much do conditionals affect performance? - c#

How much do conditionals effect performance? For example, would code A execute faster than code B since it is only checking the boolean value once? (data is a DataTable in this example)
Code A:
bool isBusiness = string.IsNullOrEmpty(data["businessName") ? false : true;
if(isBusiness) {
var name = data["businessName"];
var id = data["businessId"];
var phone = data["businessPhone"];
var address = data["businessAddress"];
}
else {
var name = data["customerName"];
var id = data["customerId"];
var phone = data["customerPhone"];
var address = data["customerAddress"];
}
Code B:
bool isBusiness = string.IsNullOrEmpty(data["businessName") ? false : true;
var name = isBusiness ? data["businessName"] : data["customerName"];
var id = isBusiness ? data["businessId"] : data["customerId"];
var phone = isBusiness ? data["businessPhone"] : data["customerPhone"];
var address = isBusiness ? data["businessAddress"] : data["customerAddress"];
This is a small example so the actual difference would be small, but what if I were mapping hundreds of rows like this? Some care about the isBusiness flag and some don't. Does anyone have any statistical evidence one way or the other?

I don't think there is a clear answer for this question. It depends on how many rows etc, the only one who can answer it is you. To test it you can simply use the Stopwatch class.
I don't think there will be many/any difference, so I would say A, since it is more readable/editable.

I agree with other responders here; however, I would like to add to this.
The performance hit incurred by if statements is something to be taken into consideration if a given method will be run often. If you would like to learn more about the specifics of this effecting performance, I recommend reading this post about conditional branching.
That being said, I will say that you get a pretty much Insignificant Performance Boost by changing the first line of code from this:
bool isBusiness = string.IsNullOrEmpty(data["businessName") ? false : true;
to this:
bool isBusiness = !string.IsNullOrEmpty(data["businessName");
Though, out of the two options I prefer the first one
The reason for this, is that if you would like to push for some code clarity, you could refactor it from this:
bool isBusiness = string.IsNullOrEmpty(data["businessName") ? false : true;
if(isBusiness) {
var name = data["businessName"];
var id = data["businessId"];
var phone = data["businessPhone"];
var address = data["businessAddress"];
}
else {
var name = data["customerName"];
var id = data["customerId"];
var phone = data["customerPhone"];
var address = data["customerAddress"];
}
to this:
bool isBusiness = !string.IsNullOrEmpty(data["businessName");
if(isBusiness) {
this.MapBusinessRow(data);
}
else {
this.MapCustomerRow(data)
}
Though, I must say, that is purely for readability and is not for performance.
At the end of the day, if you are worried about it; Test It!

Related

scope using a try catch and linq

I really have tried with this but just can't quite get it to work.
I have a bunch of files that I am using Linq to parse, but some of them have a field that the others do not have. There is no way of knowing by the file name.
Here is the code that runs against the file:
var update = from d in document.Descendants("Update")
select new
{
OrderNumber = d.Element("OrderNumber").Value,
StopID = d.Element("StopID").Value,
TransmissionTime = d.Element("TransmissionTime").Value,
EventTime = d.Element("PODTime").Value,
recordCreated = d.Element("EventTime").Value,
EventType = d.Element("EventType").Value,
EventCode = d.Element("EventCode").Value,
POD = d.Element("POD").Value,
Note = d.Element("Note").Value,
CustomerID = d.Element("CustomerID").Value,
OrderID = d.Element("OrderID").Value,
StopRef = d.Element("StopRef").Value,
PieceCount = d.Element("PieceCount").Value,
TotalWeight = d.Element("TotalWeight").Value,
DriverID = d.Element("DriverID").Value
};
Now the problem is that some of them do not have the Element("PODTime") so I need a differnet linq query. I was just going to do a try/catch and if it fails run the other one (cludgy I know).
But obviously as soon as I put update in a try/catch I can no longer access it outside of it.
Normally I would just define it before the try/catch - but I can't get that to work here.
I have tried:
System.Linq.Enumerable update = new System.Linq.Enumerable();
But that is not right. If somebody could point me the right direction I would apprecaite it.
Solution:
Using Sledgehammers nudge combined with a Let:
var update = from d in document.Descendants("Update")
let elName = d.Element("PODTime")
select new
{
OrderNumber = d.Element("OrderNumber").Value,
StopID = d.Element("StopID").Value,
TransmissionTime = d.Element("TransmissionTime").Value,
EventTime = (elName != null) ? elName.Value : string.Empty,
You can use the new ?. operator for this:
d.Element("CustomerID")?.Value
Or if you can't use the newest C#, you can write a "Safe" method to wrap all your calls in:
string SafeGetValue(XElement elem)
{
if (elem == null)
return null;
return elem.Value;
}

How to assign different enums to a variable in C#

I'm trying to do something like this..
enum Birds {
Crow,
Sparrow,
Hawk
}
enum Bugs {
Ant,
Spider,
Scorpion
}
if (featherless == true) {
var beast = Bugs;
} else {
var beast = Birds;
}
string a = (beast)2.ToString();
I have five lines of code that works on the provided enum. I can't imagine that I have to duplicate these five lines.. something like the above must be able to be used... The above structure of course causes beast to be out of scope and I can't pass var as a parameter. I know this is a headsmack moment, but I've searched and can't find a similar question.
var beastType = featherless ? typeof(Bugs) : typeof(Birds);
var a = Enum.GetValues(beastType).GetValue(2).ToString();
Will assign Hawk if featherless is true or Scorpion if it's false.
Edit 0
Maybe this will be a better solution if you only need the name:
var beastType = featherless ? typeof(Bugs) : typeof(Birds);
var a = Enum.GetName(beastType, 2);
Edit 1
Maybe you can try this if you need an object for further operations:
var beastType = featherless ? typeof(Bugs) : typeof(Birds);
var beast = Enum.ToObject(beastType, 2);
var a = beast.ToString();

Include properties based on conditions in anonymous types

Supposing I have the following anonymous type
var g = records.Select(r => new
{
Id = r.CardholderNo,
TimeIn = r.ArriveTime,
TimeOut = r.LeaveTime,
});
Is it possible to do something like the following:
var g = records.Select(r => new
{
Id = r.CardholderNo,
if (condition)
{
TimeIn = r.ArriveTime;
},
TimeOut = r.LeaveTime,
//many more properties that I'd like to be dependant on conditions.
});
How can I achieve an anonymous type based on conditions?
You can do this by using the ternary operator: ?:
The syntax is like this:
TimeIn = condition ? r.ArriveTime : (DateTime?)null // Or DateTime.Min or whatever value you want to use as default
UPDATE
After thinking about your problem for a couple of minutes I came up with the following code that you should never ever use ;)
using System;
class Program
{
static void Main(string[] args)
{
DateTime dt = DateTime.Now;
bool condition = true;
dynamic result = condition ?
(object)new
{
id = 1,
prop = dt
}
:
(object)new
{
id = 2,
};
Console.WriteLine(result.id);
if (condition) Console.WriteLine(result.prop);
}
}
This code should never be used in production because of it's terrible readability and it's really error prone. However, as a learning example of what's possible with the language it's quite nice.
Not directly using an if statement, but you could do it using the ternary operator (assuming TimeIn is of type DateTime):
var g = records.Select(r => new
{
Id = r.CardholderNo,
TimeIn = condition ? r.ArriveTime : (DateTime?)null;
TimeOut = r.LeaveTime
});
Note this will make the property always appear in your Annonymous Type. If this isn't the desired behavior, then you can't do it this way.
I would suggest thinking about the readability of your code and not only about "how can i shorten these few lines so it looks neat".
No. Anonymous types are just like any other type. It has a fixed list of properties. You can't dynamically add or remove properties.
I suggest to either set the property to null, like in the other answers, or use a Dictionary where you add the relevant properties and their values.
If you really need an if (or any another statement) in your Anonymous Type creation, you can try this not-so-pretty solution:
var g = records.Select(r => new
{
Id = r.CardholderNo,
TimeIn = new Func<DateTime?, DateTime?>(x =>
{
if (...)
return x;
else
return null;
}).Invoke(r.ArriveTime),
TimeOut = r.LeaveTime,
});

Changing data before exporting excel

I have a list which contains boolean values. I want to export that list to excel, but it must be meaningful for the customer. When I export it as it is, it shows values like True and False as expected, but these values might probably have no meaning in the perception of the customer. This is the way I do the excel export:
LiveModReports model = new LiveModReports();
List<ModerationDM.DetailedContent> liveModListDM = new List<ModerationDM.DetailedContent>();
liveModListDM = contentBLL.GetContentsForMod(modId, startDate, endDate);
if (liveModListDM != null)
{
model.ContentExcelList = new List<ContentExcel>();
foreach (var item in liveModListDM)
{
model.ContentExcelList.Add(new ContentExcel()
{
ModerasyonNumarasi = item.ModId,
Kategori = item.Category,
AltKategori = item.SubCategory,
IcerikAdresi = item.ContentURL,
IcerikSahibiTamAdi = item.ContentUFullName,
IcerikSahibiEPosta = item.ContentUserEmail,
IcerikMetni = item.ContentText,
Durumu = item.ResultCode,
SonDegistirilmeTarihi = (DateTime)item.ModifiedTime,
ModerasyonKategorisi = item.ModCategoryName,
IcerikNumarasi = item.ContentSeqNum,
BegeniPuani = item.LikeCount,
BegenilmemePuani = item.DislikeCount,
PaneldenVerilmisCevapMi = item.IsAnswer,
CevaplanmisMi = item.IsAnswered,
RaporlamaBasligi = item.ReportHeader
});
}
}
CreateExcelFile.CreateExcelDocument(model.ContentExcelList, "IcerikListesi.xlsx", System.Web.HttpContext.Current.Response);
For example, IsAnswer must be shown as "Evet" which means "Yes" in Turkish, but it's shown as "True" now. How can I change the values before they're written to excel?
You are the one preparing the model before writing it to Excel. Thus, you can simply change the properties to fit your needs.
Examples like
PaneldenVerilmisCevapMi = (item.IsAnswer) ? "Evet" : "No"
would work for you but you can do anything with these objects. Such as - passing it to a method that changes things like True to Evet or anything else that will look beter for an end user.
MakeDataReadable(model.ContentExcelList);
Use the ternary operator in order to be more meaningful with your data, for example:
PaneldenVerilmisCevapMi = (item.IsAnswer ? "Yes" : "No"),
...
Explain: if IsAnswers evaluates to true, use "Yes", otherwise, use "No".
Note that PaneldenVerilmisCevapMi must be a string.
UPDATE:
if item.IsAnswer is a nullable type, change your if statement to:
PaneldenVerilmisCevapMi = (item.IsAnswer.HasValue ? "Yes" : "No"),
You could simply write this:
PaneldenVerilmisCevapMi = (item.IsAnswer) ? "Evet" : "No"

Using strings instead of enums?

Is it common place to use a string for comparison as opposed to an enum?
I am aware about your context, but as a first step you can just refactor this way:
Step 1
if (typeOfObject == "UAV")
{
DoSomeWork(_stkObjectRootToIsolateForUavs);
}
else if (typeOfObject == "Entity")
{
DoSomeWork(_stkObjectRootToIsolateForEntities);
}
private void DoSomeWork(IAgStkObject agStkObject)
{
IAgStkObject stkObject = agStkObject.CurrentScenario.Children[stkObjectName];
IAgDataProviderGroup group = (IAgDataProviderGroup)stkUavObject.DataProviders["Heading"];
IAgDataProvider provider = (IAgDataProvider)group.Group["Fixed"];
IAgDrResult result = ((IAgDataPrvTimeVar)provider).ExecSingle(_stkObjectRootToIsolateForUavs.CurrentTime);
stkObjectHeadingAndVelocity[0] = (double)result.DataSets[1].GetValues().GetValue(0);
stkObjectHeadingAndVelocity[1] = (double)result.DataSets[4].GetValues().GetValue(0);
}
Then consider replasing if's with switch:
Step 2
switch (typeOfObject)
{
case "UAV":
DoSomeWork(_stkObjectRootToIsolateForUavs);
break;
case "Entity":
DoSomeWork(_stkObjectRootToIsolateForEntities);
break;
default:
throw new NotImplementedException():
}
This can be even better when using enums.
At the very least, the strings should be declared as constants (or perhaps readonly fields) somewhere, instead of spread out through the code. However, this looks like the schoolbook example for when to use an enum.
public enum ObjectType
{
UAV,
Entity,
// and so on
}
To add to #Restuta's answer, I'd use a
IDictionary<MyEnumifiedString, Action<IAgStkObject>>
to get rid of that if.
I'd agree with #Frederik that this seems a perfect case for using enums, but it could be that the only thing you can get out of the application is a string. In which case your example is perfectly OK.
Oh yes - and make sure you have the string constants defined in one place, preferably a config file so that if they change the other application you don't have to recompile yours.
Regarding your first question I will always use a defined type to store the strings simply to have one location for change if needed.
So for your example i would have the following
public sealed class RootTypes
{
public const string Entity = "entity";
public const string UAV = "uav";
}
Your code then updates to this
typeOfObject = typeOfObject.ToLower();
if (typeOfObject == RootTypes.UAV)
{
stkUavObject = _stkObjectRootToIsolateForUavs.CurrentScenario.Children[stkObjectName];
var group = (IAgDataProviderGroup) stkUavObject.DataProviders["Heading"];
var provider = (IAgDataProvider) group.Group["Fixed"];
IAgDrResult result = ((IAgDataPrvTimeVar) provider).ExecSingle(_stkObjectRootToIsolateForUavs.CurrentTime);
stkObjectHeadingAndVelocity[0] = (double) result.DataSets[1].GetValues().GetValue(0);
stkObjectHeadingAndVelocity[1] = (double) result.DataSets[4].GetValues().GetValue(0);
}
else if (typeOfObject == RootTypes.Entity)
{
IAgStkObject stkEntityObject = _stkObjectRootToIsolateForEntities.CurrentScenario.Children[stkObjectName];
var group = (IAgDataProviderGroup) stkEntityObject.DataProviders["Heading"];
var provider = (IAgDataProvider) group.Group["Fixed"];
IAgDrResult result = ((IAgDataPrvTimeVar) provider).ExecSingle(_stkObjectRootToIsolateForEntities.CurrentTime);
stkObjectHeadingAndVelocity[0] = (double) result.DataSets[1].GetValues().GetValue(0);
stkObjectHeadingAndVelocity[1] = (double) result.DataSets[4].GetValues().GetValue(0);
}
The issue of code redundancy has been anserwed by Restuta
Use enums with bit flags:
[Flags]
public enum MyFlags
{
SomeFlag = 0x1, // 001
OtherFlag = 0x2,// 010
ThirdFlag = 0x4 // 100
}
var firstObject = MyFlags.SomeFlag;
var secondObject = MyFlags.SomeFlag | MyFlags.OtherFlag;
if(((int)secondObject & MyFlags.SomeFlag) != 0)
{
// true
}
if(((int)secondObject & MyFlags.OtherFlag) != 0)
{
// true
}
if(((int)firstObject & MyFlags.SomeFlag) != 0)
{
// true
}
if(((int)firstObject & MyFlags.OtherFlag) != 0)
{
// false
}
This article would be helpful.

Categories