Is there a structure that handles Timeblocks? - c#

I want to handle Timeblocks, that means a set of two DateTimes which represent for example the presence of employees. Is there already any structure that i can use to search for a block before or after a specific time?
There are many ways i can imagine to express the situation, like i said with two DateTimes for start and end or with a Datetime for start and a TimeSpan. But i want them to be handled in a kind of Collection. So is there anything similar that i can use or do i have to implement it completely on my own?
Thanks

this library is a great thing - may you get inspired
Time Period Library for .NET

The class:
public class TimePeriod
{
public DateTime Oldest { get; set; }
public DateTime Newest { get; set; }
public TimePeriod(DateTime oldest, DateTime newest)
{
Oldest = oldest;
Newest = newest;
}
public bool Contains (DateTime time)
{
return Oldest.CompareTo(time) <= 0 && Newest.CompareTo(time) >= 0;
}
public bool IsAfter(DateTime time)
{
return Newest.CompareTo(time) <= 0;
}
public bool IsBefore(DateTime time)
{
return Oldest.CompareTo(time) >= 0;
}
}
The Test:
class Program
{
static void Main(string[] args)
{
var period = new TimePeriod(
DateTime.Now.AddDays(-2),
DateTime.Now.AddDays(1));
var date = DateTime.Now;
var contains = period.Contains(date); // true
var isBefore = period.IsBefore(date); // false
var isAfter = period.IsAfter(date); // false
date = DateTime.Now.AddDays(-10);
contains = period.Contains(date); // false
isBefore = period.IsBefore(date); // true
isAfter = period.IsAfter(date); // false
date = DateTime.Now.AddDays(10);
contains = period.Contains(date); // false
isBefore = period.IsBefore(date); // false
isAfter = period.IsAfter(date); // true
}
}
Now you can use collections and linq with extensions methods and lambda expression to look for time blocks.

This is not built-in. If you want to implement this yourself you probably want to create a struct. This will give you value-type copy semantics. Such a value behaves just like built-in types like int or DateTime. Very intuitive to use.

You may take a look at TimeSpan. Thats a struct to handle a "Timeblock"

I've used a DateSpan structure before. You can extend is a much as one likes, but this will give you a starting point.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace StackOverFlowDateSpan
{
[StructLayout(LayoutKind.Auto)]
[Serializable]
public struct DateSpan : IComparable, IComparable<DateSpan>, IEquatable<DateSpan>
{
public DateSpan(DateTime start, DateTime end)
: this()
{
Start = start;
End = end;
}
#region Properties
public TimeSpan Duration
{
get { return TimeSpan.FromTicks((End - Start).Ticks); }
}
public DateTime End { get; private set; }
public DateTime Start { get; private set; }
#endregion
public int CompareTo(DateSpan other)
{
long otherTicks = other.Duration.Ticks;
long internalTicks = Duration.Ticks;
return internalTicks > otherTicks ? 1 : (internalTicks < otherTicks ? -1 : 0);
}
public bool Equals(DateSpan other)
{
return End.Equals(other.End) && Start.Equals(other.Start);
}
public int CompareTo(object other)
{
if (other == null)
{
return 1;
}
if (!(other is DateSpan))
{
throw new ArgumentNullException("other");
}
return CompareTo((DateSpan)other);
}
public override bool Equals(object other)
{
if (ReferenceEquals(null, other))
{
return false;
}
return other is DateSpan && Equals((DateSpan)other);
}
public override int GetHashCode()
{
unchecked
{
return (End.GetHashCode() * 397) ^ Start.GetHashCode();
}
}
public static bool operator ==(DateSpan left, DateSpan right)
{
return left.Equals(right);
}
public static bool operator !=(DateSpan left, DateSpan right)
{
return !left.Equals(right);
}
private sealed class EndStartEqualityComparer : IEqualityComparer<DateSpan>
{
#region IEqualityComparer<DateSpan> Members
public bool Equals(DateSpan x, DateSpan y)
{
return x.End.Equals(y.End) && x.Start.Equals(y.Start);
}
public int GetHashCode(DateSpan obj)
{
unchecked
{
return (obj.End.GetHashCode() * 397) ^ obj.Start.GetHashCode();
}
}
#endregion
}
private static readonly IEqualityComparer<DateSpan> _endStartComparerInstance = new EndStartEqualityComparer();
public static IEqualityComparer<DateSpan> EndStartComparer
{
get { return _endStartComparerInstance; }
}
}
}

Thanks for the help! I will tae a closer look at the TimePeriod Library and do some experiments with Linq. I already have an approch that implements binary search, so if someones interested you can write me ;)

Related

Create an Unit Test for Generic Method

I have the following class:
public class Range<T> where T : IComparable<T> {
public T Minimum { get; set; }
public T Maximum { get; set; }
public Range(T minimum, T maximum) {
Minimum = minimum;
Maximum = maximum;
}
public Boolean Contains(T value) {
return (Minimum.CompareTo(value) <= 0) && (value.CompareTo(Maximum) <= 0);
}
}
I am using XUnit to create my Unit Tests ...
How should I test the Contains method that has T?
As has been stated, you could test it with an int which might look something like this:
var range = new Range<int>(minimum: 3, maximum: 7);
Assert.IsTrue(range.Contains(5));
You need to create an instance of an IComparable and for thoroughness (true unit testing) I would suggest a mocking library with the ability to verify calls. I would probably use something like Moq. You will need an object that implements the interface, which you might have already or you could create a test one with no actual implemetation.
public class YourObject : IComparable<YourObject>
{
public virtual int CompareTo(YourObject other)
{
throw new NotImplementedException();
}
}
I would make a subtle change your Range code just a bit for consistency:
public class Range<T> where T : IComparable<T>
{
public T Minimum { get; set; }
public T Maximum { get; set; }
public Range(T minimum, T maximum)
{
Minimum = minimum;
Maximum = maximum;
}
public Boolean Contains(T value)
{
return (Minimum.CompareTo(value) <= 0) && (Maximum.CompareTo(value) >= 0);
}
}
The end result is identical but it makes things a bit easier while setting up the mocks. Or you could go with value.CompareTo on both accounts. Either way it would add a little more consistency.
The test code would look a little like this:
var min = new Mock<YourObject>();
var max = new Mock<YourObject>();
var val = new Mock<YourObject>();
var range = new Range<YourObject>(min.Object, max.Object);
min.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(-1);
max.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(1);
Assert.True(range.Contains(val.Object));
min.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(0);
max.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(1);
Assert.True(range.Contains(val.Object));
min.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(-1);
max.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(0);
Assert.True(range.Contains(val.Object));
min.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(1);
max.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(1);
Assert.False(range.Contains(val.Object));
min.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(-1);
max.Setup(m => m.CompareTo(It.IsAny<YourObject>())).Returns(-1);
Assert.False(range.Contains(val.Object));
Now you are testing your Range class's Contains method and not the object's ability to return the correct value when it's CompareTo is called.
Happy Coding!

How to find an item on a generic List using IEqualityComparer? [duplicate]

I wrote a class of account objects and hold a static List<T> of those account objects. My program loops through each account in the list, performing some work with the account, and then resetting at the top when it reaches the end of the list.
My issue is that I need to be able to reinsert the account into the list after my program finishes working with it, with some updated info added. Can I do this as written below, using the IndexOf() function to check for the object in the static list or will it fail because I added data to it? I don't understand which fields it compares to see if the two objects are the same.
Note: no duplicates are allowed in the list so there is no risk of updating the wrong item
public class Account
{
public string name;
public string password;
public string newInfo;
}
public static class Resources
{
private static List<Account> AccountList = new List<Account>();
private static int currentAccountIndex = 0;
public static Account GetNextAccount()
{
if (currentAccountIndex > AccountList.Count)
currentAccountIndex = 0;
return AccountList[currentAccountIndex++];
}
public static void UpdateAccount(Account account)
{
int index;
if ((index = AccountList.IndexOf(account)) >= 0)
AccountList[index] = account;
}
}
public class Program
{
public void PerformWork()
{
Account account = Resources.GetNextAccount();
// Do some work
account.newInfo = "foo";
Resources.UpdateAccount(account);
}
}
Another option is to use List.FindIndex, and pass a predicate. That is:
if ((index = AccountList.FindIndex(a => a.name == account.name)) >= 0)
AccountList[index] = account;
That way you can search on any arbitrary field or number of fields. This is especially useful if you don't have access to the source code for Account to add an overloaded Equals method.
One thing the accepted answer did not cover is you are supposed to override Equals(object) and GetHashCode() for IEquatable<T> to work correctly. Here is the full implementation (based off of keyboardP's answer)
public class Account : IEquatable<Account>
{
public string name;
public string password;
public string newInfo;
private readonly StringComparer comparer = StringComparer.OrdinalIgnoreCase;
public override bool Equals(object other)
{
//This casts the object to null if it is not a Account and calls the other Equals implementation.
return this.Equals(other as Account);
}
public override int GetHashCode()
{
return comparer.GetHashCode(this.newInfo)
}
public bool Equals(Account other)
{
//Choose what you want to consider as "equal" between Account objects
//for example, assuming newInfo is what you want to consider a match
//(regardless of case)
if (other == null)
return false;
return comparer.Equals(this.newInfo, other.newInfo);
}
}
Your object should implement the IEquatable interface and override the Equals method.
public class Account : IEquatable<Account>
{
public string name;
public string password;
public string newInfo;
public bool Equals(Account other)
{
//Choose what you want to consider as "equal" between Account objects
//for example, assuming newInfo is what you want to consider a match
//(regardless of case)
if (other == null)
return false;
return String.Equals(this.newInfo, other.newInfo,
StringComparison.OrdinalIgnoreCase);
}
}
If your class properly implements IEquatable<T>, then IndexOf() will use your Equals() method to test for equality.
Otherwise, IndexOf() will use reference equality.
You can use a custom Predicate for your class, such as:
public class Account
{
public string name;
public string password;
public string newInfo;
public class IndexOfName
{
private string _match = "";
public IndexOfName()
{
}
public Predicate<Account> Match(string match)
{
this._match = match;
return IsMatch;
}
private bool IsMatch(Account matchTo)
{
if (matchTo == null)
{
return false;
}
return matchTo.Equals(this._match);
}
}
}
Then you can use it as follow:
Account.IndexOf indexOf = new Account.IndexOf();
int index;
if ((index = AccountList.FindIndex(indexOf.Match("john"))) > 0)
{
// do something with John
}
if ((index = AccountList.FindIndex(indexOf.Match("jane"))) > 0)
{
// do something with Jane
}
You could even change the IndeOfName class to use a flag to switch between the type of info you are looking for. Ex: name or newInfo.

Possible to declare an interface containing an extension?

As part of a testing library, I would like to define an interface which says 'this object knows how to initialize itself randomly'. If members of the randomly filled object are references, the random initialization should be capable of assigning null to these members.
If I was doing this for one class, the code could look like this
public class QWorker
{
double mxVal = 0;
public void fillRandomly(System.Random xRng)
{
mxVal = xRng.NextDouble();
}
}
public class QBoss
{
public QWorker mxWorker;
void fillRandomly(System.Random xRng)
{
if (xRng.Next() % 2 == 1)
x1 = null;
else
{
x1 = new QWorker();
x1.fillRandomly(xRng);
}
}
}
Now if QBoss had mulitple reference-type members, if/else would have to be done for every member. It would look ugly and could be cumbersome to maintain. To cimrcumvent, I came up with the following sample code:
public interface QIRandomizable<T> where T : new()
{
static void fillRandomly(this System.Random xThis, ref T xRef); // XXX
}
class QWorker : QIRandomizable<QWorker>
{
public double mxDouble;
}
public static class QWorkerExtensions
{
public static void fillRandomly(this System.Random xThis, ref QWorker xRef)
{
if ((xThis.Next() % 2) == 1)
xRef = null;
else
{
xRef = new QWorker();
xRef.mxDouble = xThis.NextDouble();
}
}
}
public class QBoss : QIRandomizable<QBoss>
{
public QWorker mx1;
public QWorker mx2;
public static void fillRandomly(this System.Random xThis, ref QBoss xRef)
{
xRef = new QBoss();
xThis.fillRandomly(ref xRef.mxMember1); // can be null
xThis.fillRandomly(ref xRef.mxMember2); // can be null
}
}
However this does not compile and the first problem is on line marked XXX - the static keyword does not belong there.
As a result, I would like to ask the following:
Is it possible to declare an interface with an extension inside?
If yes, what should I change?
If not, is there a different way how to accomplish what I want?
Any help is much appreciated,
Daniel
No, you cannot. That's because you can only declare instance-methods on an interface, and extension methods must be static.
You can try something like this:
public interface IDoesSomething
{
void fillRandomly(Random r);
}
public class QBoss
{
public double mx1 { get; set; }
public double mx2 { get; set; }
public int mx3 { get; set; }
public object refType { get; set; }
public void fillRandomly(Random r)
{
FillRandom(GetProps(this), this, r);
}
}
public static IEnumerable<PropertyInfo> GetProps(object blah)
{
return blah.GetType().GetProperties();
}
public static void FillRandom(IEnumerable<PropertyInfo> obj, object onObj, Random r)
{
Action<PropertyInfo, object> setVal = (prop, val) => { prop.SetValue(onObj, val); };
foreach (var o in obj)
{
if (!o.PropertyType.IsValueType)
{
if (r.Next() % 2 != 1)
{
var v = Activator.CreateInstance(o.PropertyType);
setVal(o, v);
var id = v as IDoesSomething;
if (id != null)
id.fillRandomly(r);
}
}
if (o.PropertyType == typeof(double))
setVal(o, r.NextDouble());
if (o.PropertyType == typeof(int))
setVal(o, (int)(r.NextDouble() * 100));
//etc, etc
}
}
Here, you decide what to do once, and set the properties. This currently only works for properties, not fields, so you might want to refactor it a little to take both FieldInfo and PropertyInfo
Testing it yields:
mx1 0.786868741170908
mx2 0.434705327001729
mx3 51
refType Object

c# - Public Class with index accessor

I want to create a global accessible struct/class (in C#) to access my stock prices from the callback handler.
I know only C and it's easy there
Example in C
struct _Sample
{
int SomeValue;
};
struct _Sample Sample[10];
That's what I have so far in C# after 2 hours of trying.
public static class GlobalVar
{
private static double _StockPrice;
public static double SetStockPrice
{
set
{
_StockPrice = value;
}
}
public static double GetStockPrice
{
get
{
return _StockPrice;
}
}
}
The above example can be used as GlobalVar.SetStockPrice = 10.254; I know I have to use the <List> to make _StockPrice available as an array, but all my attempts to compile a working solution failed.
I would like to access it as GlobalVar[1].SetStockPrice = 1.0; and GlobalVar[1].SetStockPrice = 1.0;
I have to use C# because the SDK I'm using is only available in C#.
You would have to add a StockPrice class and keep an internal dictionary inside of GlobalVar to make this work, but you could use this:
public StockPrice this[int index]
{
get
{
StockPrice stockPrice = null;
if (index > -1)
{
InternalDictionary.TryGetValue(index, out stockPrice);
}
return stockPrice;
}
}
Then you can do GlobalVar[index] to get a certain StockPrice object from that internal dictionary of GlobalVar.
Also note that this will not work on a static class because static indexers are not allowed in C#. You might want to change your class to be a singleton instead of a static.
EDIT: A more complete example (still needs work though) with a singleton implementation:
public class GlobalVars
{
static StockPrices _stockPrices = new StockPrices();
public static StockPrices StockPrices
{
get
{
return _stockPrices ;
}
}
}
public class StockPrices
{
Dictionary<int, StockPrice> InternalDictionary = new Dictionary<int, StockPrice>();
public StockPrice this[int index]
{
get
{
StockPrice stockPrice = null;
if (index > -1)
{
InternalDictionary.TryGetValue(index, out stockPrice);
}
return stockPrice;
}
}
public void Add(StockPrice stockPrice)
{
int index = InternalDictionary.Keys.Max() + 1;
InternalDictionary.Add(index, stockPrice);
}
}
Then you could call your code like this:
GlobalVars.StockPrices[1].DoSomething
The C example you gave, is creating an array with 10 instances of the struct.
The equivalent C# code is this:
struct _Sample
{
public int SomeValue;
public static _Sample[] Sample = new _Sample[10];
};
That is not very C#-ish however. Using C# style I would write something like
struct Sample
{
public int SomeValue { get; set; }
public static Sample[] Values = new Sample[10];
}
You can do something like this to have the same behaviour like in c. Notice that you don't need to make SetField and GetField using { get; set; } you get this behaviour by default (it's a property).
public struct Sample
{
public double StockPrice { get; set; }
}
public static class GlobalVar
{
public static Sample[] Samples = new Sample[10];
}
And to acces use
GlobalVar.Samples[1].StockPrice = 1.0;

Why I cannot set ANY value in IF condition?

I have 2 static variables like below
private static DateTime _currentPollStartDate = DateTime.MinValue; //As Default
private static DateTime _currentPollEndDate = DateTime.MinValue; //As Default
In a method, I try to set the values:
public void ProcessItems()
{
var Items = GetItems();
//In here, it reaches inside
if (Items.HasItems)
{
//Items[0].PollStartDate.HasValue is TRUE
//I can NOT set either Items[0].PollStartDate.Value or DateTime.MaxValue
_currentPollStartDate = Items[0].PollStartDate.HasValue ? Items[0].PollStartDate.Value : DateTime.MaxValue;
//Items[0].PollEndDate.HasValue is TRUE
//I can NOT set either Items[0].PollEndDate.Value or DateTime.MaxValue
_currentPollEndDate = Items[0].PollEndDate.HasValue ? Items[0].PollEndDate.Value : DateTime.MaxValue;
}
//...
}
But when I do this with IF I don't have the problem as stated above, why?
public void ProcessItems()
{
var Items = GetItems();
//In here, it reaches inside
if (Items.HasItems)
{
if (Items[0].PollStartDate.HasValue)
_currentPollStartDate = Items[0].PollStartDate.Value;
if (Items[0].PollEndDate.HasValue)
_currentPollEndDate = Items[0].PollEndDate.Value;
}
//...
}
Also, when I declare the variables not static this also solves my problem even though I use it like in my first code. But why can't I use both static and if statement as in my first code?
Edit:
Expected Value: something like
_currentPollStartDate -> 2013-04-18 10:03:03
Result Value:
_currentPollStartDate -> 0001-01-01 00:00:00 (This is not even MAX value)
Thank to Ken Kin. With his latest comment, I thought to use of properties instead of simple declaration. So instead of this below:
private static DateTime _currentPollStartDate = DateTime.MinValue; //As Default
private static DateTime _currentPollEndDate = DateTime.MinValue; //As Default
I did as
private static DateTime CurrentPollStartDate { set; get; }
private static DateTime CurrentPollEndDate { set; get; }
and it worked.
static means "only once per class". so all instances of your class will use the same (by the exact meaning of the word) variable you defined as static. To make your code work use:
YourClassName._currentPollStartDate = Items[0].PollStartDate.HasValue ? Items[0].PollStartDate.Value : DateTime.MaxValue;
I don't know if you really want to have the same start and end date for all your polls which means the newest poll changes the start and end date of all your older polls.
Check for the type of Items[0].PollStartDate.Value and DateTime.MaxValue, when they are used with the trinary operator, both branches must be the same type.
bool and bool?, or int and int? are not the same type.
update:
I declared the following with no problem:
class MyClassName {
private static DateTime _currentPollStartDate=DateTime.MinValue; //As Default
private static DateTime _currentPollEndDate=DateTime.MinValue; //As Default
public void ProcessItems() {
var Items=GetItems();
//In here, it reaches inside
if(Items.HasItems) {
//Items[0].PollStartDate.HasValue is TRUE
//I can NOT set either Items[0].PollStartDate.Value or DateTime.MaxValue
_currentPollStartDate=Items[0].PollStartDate.HasValue?Items[0].PollStartDate.Value:DateTime.MaxValue;
//Items[0].PollEndDate.HasValue is TRUE
//I can NOT set either Items[0].PollEndDate.Value or DateTime.MaxValue
_currentPollEndDate=Items[0].PollEndDate.HasValue?Items[0].PollEndDate.Value:DateTime.MaxValue;
}
//...
}
public void _ProcessItems() {
var Items=GetItems();
//In here, it reaches inside
if(Items.HasItems) {
if(Items[0].PollStartDate.HasValue)
_currentPollStartDate=Items[0].PollStartDate.Value;
if(Items[0].PollEndDate.HasValue)
_currentPollEndDate=Items[0].PollEndDate.Value;
}
//...
}
Items GetItems() {
return new Items();
}
}
class Items: List<Item> {
public bool HasItems {
get;
set;
}
}
class Item {
public DateTime? PollStartDate {
get;
set;
}
public DateTime? PollEndDate {
get;
set;
}
}

Categories

Resources