How to assign different enums to a variable in C# - 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();

Related

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"

How much do conditionals affect performance?

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!

Dynamically Generate Codes in C#

I have a list of Enums like the following:
public enum Evaluation : int
{
//Section 1
S1_1_1 = 579,
S1_1_2 = 584,
S1_1_3 = 589,
S1_1_4 = 594,
S1_1_5 = 599,
S1_1_6 = 604,
//Section 2
S1_2_1 = 610,
S1_2_2 = 615,
S1_2_3 = 620,
S1_2_4 = 625,
S1_2_5 = 630,
};
I want to iterate each section and use the values dynamically
int S1Count = 6;
for (int i = 1; i <= S1Count; i++)
{
VoteCount += string.IsNullOrEmpty(this.GetEvaluationValue(FormID, Evaluation.S1_1_ + i)) ? 0 : 1;
}
How can I achieve that? Thanks.
Sorry, my mistake. I tried to get the value from the database by using enum values which are IDs and I have to calculate counts, average for each section.
You can use Enum.Parse to do what you want I think though I don't reccomend it.
To use enum.Parse you'd just need to do something like:
Enum.Parse(typeof(Evaluation), String.Format("S1_1_{0}",i));
This does point at you using some dodgy methodology though. As I said in comments above you would be better off with a data structure allowing you to have sections and their contents easily differentiated. You can do this with either custom classes or maybe just a dictionary of Lists of ints...
Dictionary<int, List<int>> SectionContents;
and use it like:
foreach(int id in SectionContents[sectionNumber])
{
VoteCount += string.IsNullOrEmpty(this.GetEvaluationValue(FormID, id)) ? 0 : 1;
}
(I don't vouch for what's in the foreach, I'm just demonstrating how a dictionary of a list of ints could work).
Creating the Dictionary is easy enough and doesn't require enums. And if this is database stuff could easily be generated through a database query to get the IDs and what sections they are in and then create the data structure.
This will do it
public class Program
{
public static void Main()
{
foreach (FieldInfo fInfo in typeof(Evaluation).GetFields(BindingFlags.Public | BindingFlags.Static))
{
Console.WriteLine("Evaluation." + fInfo.Name);
}
Console.ReadLine();
}
}

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