Generics and IList related - c#

i have this code below -- a generic method which takes List as one of the input parameters. within the method, is an IF/ELSEIF statement, which runs into a common LINQ call.
Please help me out, so that the LINQ, call could be common to all the IF/ELSEIF's.
private Boolean filterList<T>(List<T> anyOutdoorSports, int numberOfPartcipants)
{
if (anyOutdoorSports == null){ return false ;}
Boolean _returnValue = false;
if (anyOutdoorSports.GetType() == typeof(List<Swimming>))
{
List<Swimming> Swimming = anyOutdoorSports.Cast<Swimming>().ToList();
if (Swimming.Count > 0)
{
int listCount = (from rca in Swimming
where (rca.RecordFields[numberOfPartcipants].ToString()).StartsWith("stamina")
select rca).Count();
_returnValue = listCount > 0 ? true : false;
}
}
else if (anyOutdoorSports.GetType() == typeof(List<Tennis>))
{
List<Tennis> Tennis = anyOutdoorSports.Cast<Tennis>().ToList();
if (Tennis.Count > 0)
{
int listCount = (from rca in Tennis
where (rca.RecordFields[numberOfPartcipants].ToString()).StartsWith("stamina")
select rca).Count();
_returnValue = listCount > 0 ? true : false;
}
}
else if (anyOutdoorSports.GetType() == typeof(List<Soccer>))
{
List<Soccer> Soccer = anyOutdoorSports.Cast<Soccer>().ToList();
if (Soccer.Count > 0)
{
int listCount = (from rca in Soccer
where (rca.RecordFields[numberOfPartcipants].ToString()).StartsWith("stamina")
select rca).Count();
_returnValue = listCount > 0 ? true : false;
}
}
return _returnValue;
}
THANKS TO ALL WHO VIEWED AND HELPED.

This is straightforward if there is a common base class for Tennis, Soccer and Swimming with a RecordFields property:
private boolean FilterList<T>(IEnumerable<T> anyOutdoorSports, int numberOfParticipants) where T : OutdoorSport
{
if(anyOutdoorSports == null) return false;
return anyOutdoorSports.Any(s => s.RecordFields[numberOfParticipants].ToString().StartsWith("stamina"));
}

Since all of your types seem to have an RecordFields property you could add an Interface and use that instead of the Generic.
Other than that you'd have to resort to Func<> expressions.

Assuming that all the classes inherit from the same base class, which contains RecordFields, you can create a generic constraint on the method and remove the ifs entirely.
private Boolean filterList<T>(List<T> anyOutdoorSports, int numberOfPartcipants)
where T : OutdoorSport
{
if (anyOutdoorSports == null){ return false ;}
Boolean _returnValue = false;
if (anyOutdoorSports.Count > 0)
{
int listCount = (from rca in anyOutdoorSports
where (rca.RecordFields[numberOfPartcipants].ToString()).StartsWith("stamina")
select rca).Count();
_returnValue = listCount > 0;
}
return _returnValue;
}

Related

Skip foreach X positions

I want skip my in foreach. For example:
foreach(Times t in timeList)
{
if(t.Time == 20)
{
timeList.Skip(3);
}
}
I want "jump" 3 positions in my list.. If, in my if block t.Id = 10 after skip I want get t.Id = 13
How about this? If you use a for loop then you can just step the index forward as needed:
for (var x = 0; x < timeList.Length; x++)
{
if (timeList[x].Time == 20)
{
// option 1
x += 2; // 'x++' in the for loop will +1,
// we are adding +2 more to make it 3?
// option 2
// x += 3; // just add 3!
}
}
You can't modify an enumerable in-flight, as it were, like you could the index of a for loop; you must account for it up front. Fortunately there are several way to do this.
Here's one:
foreach(Times t in timeList.Where(t => t.Time < 20 || t.Time > 22))
{
}
There's also the .Skip() option, but to use it you must break the list into two separate enumerables and then rejoin them:
var times1 = timeList.TakeWhile(t => t.Time != 20);
var times2 = timeList.SkipeWhile(t => t.Time != 20).Skip(3);
foreach(var t in times1.Concat(times2))
{
}
But that's not exactly efficient, as it requires iterating over the first part of the sequence twice (and won't work at all for Read Once -style sequences). To fix this, you can make a custom enumerator:
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> items, Predicate<T> SkipTrigger, int SkipCount)
{
bool triggered = false;
int SkipsRemaining = 0;
var e = items.GetEnumerator();
while (e.MoveNext())
{
if (!triggered && SkipTrigger(e.Current))
{
triggered = true;
SkipsRemaining = SkipCount;
}
if (triggered)
{
SkipsRemaining--;
if (SkipsRemaining == 0) triggered = false;
}
else
{
yield return e.Current;
}
}
}
Then you could use it like this:
foreach(Times t in timeList.SkipAt(t => t.Times == 20, 3))
{
}
But again: you still need to decide about this up front, rather than inside the loop body.
For fun, I felt like adding an overload that uses another predicate to tell the enumerator when to resume:
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> items, Predicate<T> SkipTrigger, Predicate<T> ResumeTrigger)
{
bool triggered = false;
var e = items.GetEnumerator();
while (e.MoveNext())
{
if (!triggered && SkipTrigger(e.Current))
{
triggered = true;
}
if (triggered)
{
if (ResumeTrigger(e.Current)) triggered = false;
}
else
{
yield return e.Current;
}
}
}
You can use continue with some simple variables.
int skipCount = 0;
bool skip = false;
foreach (var x in myList)
{
if (skipCount == 3)
{
skip = false;
skipCount = 0;
}
if (x.time == 20)
{
skip = true;
skipCount = 0;
}
if (skip)
{
skipCount++;
continue;
}
// here you do whatever you don't want to skip
}
Or if you can use a for-loop, increase the index like this:
for (int i = 0; i < times.Count)
{
if (times[i].time == 20)
{
i += 2; // 2 + 1 loop increment
continue;
}
// here you do whatever you don't want to skip
}

Return false if type properties equals null or 0

I tried following the method as follows here: Checking if Object has null in every property . However, when instantiating Order newOrder = new Order();. I cannot simple just implement bool props = newOrder.ArePropertiesNotNull(). What am I supposed to add to my Order class? And where do I implement the function for ArePropertiesNotNull<T>(this T obj)? I would like to know if there is a way to return false if value returned equals 0 or null?
Here is my code:
OrderProdRepository.cs
...
public bool ReadFromFile(string _date)
{
taxesFile.ReadFile();
productsFile.ReadFile();
string orderFileName = $"C:\\tempfolder\\Orders_{_date}.txt";
List<string> lines = File.ReadAllLines(orderFileName).ToList();
foreach (var line in lines.Skip(1)) //?? new List<string>(0)
{
List<string> entry = line.Split(',').ToList();
Order newOrder = new Order();
int.TryParse(entry[0], out int orderNumber);
newOrder.OrderNumber = orderNumber;
newOrder.Date = _date;
newOrder.CustomerName = entry[1];
newOrder.State = taxesFile.StateAbbreviation(entry[2]);
newOrder.StateName = taxesFile.StateName(newOrder.State);
decimal.TryParse(entry[3], out decimal taxRate);
newOrder.TaxRate = taxesFile.TaxRate(taxRate);
newOrder.ProductType = productsFile.ProductType(entry[4]);
decimal.TryParse(entry[5], out decimal area);
newOrder.Area = area;
decimal.TryParse(entry[6], out decimal costPerSquareFoot);
newOrder.CostPerSquareFoot = productsFile.CostPerSquareFoot(costPerSquareFoot);
decimal.TryParse(entry[7], out decimal laborCostPerSquareFoot);
newOrder.LaborCostPerSquareFoot = productsFile.LaborCostPerSquareFoot(laborCostPerSquareFoot);
decimal.TryParse(entry[8], out decimal materialCost);
newOrder.MaterialCost = materialCost;
decimal.TryParse(entry[9], out decimal laborCost);
newOrder.LaborCost = laborCost;
decimal.TryParse(entry[10], out decimal tax);
newOrder.Tax = tax;
decimal.TryParse(entry[11], out decimal total);
newOrder.Total = total;
orderList.Add(newOrder);
}
return true;
}
...
I think you need a function to check each line for null and/or 0 values:
private bool IsValidLine(string line)
{
if (line == null)
return false;
var arr = line.Split(',');
//Uncomment this if splitting the line will always return 11 items array.
//if (arr.Length < 11)
// return false;
return arr.Aggregate(0, (n, s) =>
(decimal.TryParse(s, out decimal d) && d == 0) ||
string.IsNullOrWhiteSpace(s) ? n + 1 : n) == 0;
}
You can use it in your code as follows:
public bool ReadFromFile(string _date)
{
var orderFileName = $"C:\\tempfolder\\Orders_{_date}.txt";
var lines = File.ReadAllLines(orderFileName);
foreach (var line in lines.Skip(1))
{
//If parsing any line returns false.
if (!IsValidLine(line))
return false;
//Or if you need to create a list of the valid Order entries.
if (IsValidLine(line))
{
var order = new Order();
//...
orderList.Add(newOrder);
}
}
return true;
}
Alternatives:
Add a static function in the Order class to parse a given line and return a new object of Order type if the line is valid. Something like this.
If its not too late, then consider using a local database or serialization. Something like this and maybe this if you don't mind a vb.net example.
You need to create this method an extension method. It should be defined in static class:
public static class ObjectExtensions
{
public static bool ArePropertiesNotNull<T>(this T obj)
{
return typeof(T).GetProperties().All(propertyInfo => propertyInfo.GetValue(obj) != null);
}
}

Check List order is wrong or right , How to make code clear

I want to check list order is right or worng , And my solution be here.
it worked , But it look dirty & stupid , Have any better soultion can do that ?
I add two example to explain is case .
public enum HI
{
A,
B,
C
}
public class Test : MonoBehaviour
{
public void TestOroder()
{
// check hiList order ----> A >B >C
List<HI> hiList = new List<HI>() { HI.A, HI.B, HI.B, HI.B, HI.C , HI.C , HI.C };
//right
bool isRight = FindWorngOrder(hiList);
// check hiList order ----> A >B >C
List<HI> hiList2 = new List<HI>() { HI.A, HI.B, HI.C, HI.A ,HI.B, HI.B, HI.C };
//worng
bool isRight2 = FindWorngOrder(hiList);
}
public bool FindWorngOrder(List<HI> hiList)
{
bool haveWorngOrder;
for (int i = 0; i < hiList.Count - 1; i++)
{
HI current = hiList[i];
HI next = hiList[i + 1];
if (current == HI.C && next == HI.A ||
current == HI.C && next == HI.B)
{
return true;
}
if (current == HI.C && next == HI.B)
{
return true;
}
}
return false;
}
}
I'd suggest using:
public bool IsInTheSamerOrder(IEnumerable<HI> hiList)
{
return hiList.SequenceEqual(hiList.OrderBy(z => z));
}
It is similar to your answer, but slightly shorter and doesn't need the explicit List.
by #mjwills answer
public bool FindWorngOrder(List<HI> hiList)
{
List<HI> orderd = hiList.ToList();
orderd.Sort();
return orderd.SequenceEqual(hiList);
}

Simple 2 Boolean Efficiency

Just a quick one guys - y'know when your brain hurts just looking at something. Just seeing if there is a "better" way to do this in terms of boolean logic.
private RegenerationType AccquireRegenerationState (int floor, int playerFloor)
{
bool entranceExists = (floorBlocks[floor].doorBlocks.Count != 0) ? true : false;
if (floor + 1 == playerFloor || !floorBlocks[floor + 1].isVisited)
{
if (entranceExists)
{
return RegenerationType.Still;
}
else
{
return RegenerationType.Limit;
}
}
else
{
if (entranceExists)
{
return RegenerationType.Prime;
}
else
{
return RegenerationType.Full;
}
}
}
I guess that's the best you can achieve. Of course, assuming that you maintain code readability and clearness:
private RegenerationType AccquireRegenerationState (int floor, int playerFloor)
{
var entranceExists = floorBlocks[floor].doorBlocks.Count != 0;
var whatever = floor + 1 == playerFloor || !floorBlocks[floor + 1].isVisited;
if (whatever)
{
return entranceExists ? RegenerationType.Still : RegenerationType.Limit;
}
else
{
return entranceExists ? RegenerationType.Prime : RegenerationType.Full;
}
}
bool entranceExists = (floorBlocks[floor].doorBlocks.Count != 0);
return
(floor + 1 == playerFloor || !floorBlocks[floor + 1].isVisited)?
(entranceExists? RegenerationType.Still: RegenerationType.Limit):
(entranceExists? RegenerationType.Prime: RegenerationType.Full);

LINQ TO SQL: Detect existing data

I need LINQ code to be able to detect if an entry is input but the datum already exists in the table.
public Boolean CheckAssessment(String assessmentName)
{
{
SQL_TA_SCOREBOARDEntities1 d = new SQL_TA_SCOREBOARDEntities1();
Assessment A_List = new Assessment();
{
var qry2 = from b in contxt.View_Assessment
where b.AssessmentName == assessmentName
select b;
if (qry2 = assessmentName.ToString())
{
return true;
}
else
{
return false;
}
}
}
}
Where assessmentName is the value of the textbox in the a separate C# class.
Boolean i;
i = TAClass.CheckAssessment(txtAssessmentName.ToString());
if (i == true)
{
Label2.Text = "Assessment name already exists.";
}
The correct way is to use Any() extension method. Any() will generate optimized query and will return true as soon as the query found the record.
http://msdn.microsoft.com/en-us/library/bb534338.aspx
So, in your CheckAssessment method, you can do like this:
return (from b in assessments
where b.AssessmentName == assessmentName
select b).Any();
Use the Count() extension to check if there are any matching records:
public bool CheckAssessment(string assessmentName)
{
return (from b in contxt.View_Assessment
where b.AssessmentName == assessmentName
select b).Count() > 0;
}
UPDATE: just for your knowledge, your code could work this way:
public Boolean CheckAssessment(String assessmentName)
{
{
SQL_TA_SCOREBOARDEntities1 d = new SQL_TA_SCOREBOARDEntities1();
Assessment A_List = new Assessment();
{
var qry2 = (from b in contxt.View_Assessment
where b.AssessmentName == assessmentName
select b.AssessmentName).FirstOrDefault();
if (qry2 = assessmentName.ToString())
{
return true;
}
else
{
return false;
}
}
}
}
Just one more comment, always that you have something like:
if (a) { return true; } else {return false;}
you can replace by
return a;

Categories

Resources