Why I cannot set ANY value in IF condition? - c#

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;
}
}

Related

C# Basic parameter passing

I am new to C# I am trying to pass a value to a method but receiving 0.Creating an instance to the main method of calc and calling the calc methods in main.
public void test()
{
var calc = new Calc();
calc.Add(1);
var actual = calc.Value;
}
public class Calc
{
public int Value{
get; set;
}
public void Add(int value)
{
int result = value + value;
}
I am trying to set the current value, how could I do that?
I'd suggest refactoring it a bit so the variable names are more clear. Your initial problem is that you weren't doing anything with the result, when really you wanted to set it to your property.
public class Calc
{
public int CurrentValue { get; set; }
public void Add(int number)
{
this.CurrentValue = this.CurrentValue + number;
}
}
The result of your Add method is not stored anywhere, i.e. the after the method is complete all the memory allocated while it was executed, is released. If you wish to save the result of your method you should either return it (which will require changing your method's prototype) or save it in a member of you class and access it with an appropriate property or getter-method.
Your class should be something like this:
public class Calc
{
private int result;
public int Value
{
get { return result; }
set { result = value; }
}
public void Add(int value)
{
result = value + value;
}
}
Please note that currently the Add methods just saves the result of two times of the value of the sent parameter value into the class member result
I think you want something more like this:
public class Calc
{
public int Value{
get; private set;
}
public void Add(int value)
{
this.Value += value;
}
}
Note I changed your Value to have a private setter, so that only the Calc class has access to change its value, whereas other objects are still able to retrieve its value.
Notice the change in the Add function, we're adding the value passed into the function onto your Value property. In your case you were just creating a new variable result in each call of the Add method, and then doing nothing with it.
You can see it in action here

Too many calculated properties in my class

I have class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}

Can't serialize Timespan value [duplicate]

I am trying to serialize a .NET TimeSpan object to XML and it is not working. A quick google has suggested that while TimeSpan is serializable, the XmlCustomFormatter does not provide methods to convert TimeSpan objects to and from XML.
One suggested approach was to ignore the TimeSpan for serialization, and instead serialize the result of TimeSpan.Ticks (and use new TimeSpan(ticks) for deserialization). An example of this follows:
[Serializable]
public class MyClass
{
// Local Variable
private TimeSpan m_TimeSinceLastEvent;
// Public Property - XmlIgnore as it doesn't serialize anyway
[XmlIgnore]
public TimeSpan TimeSinceLastEvent
{
get { return m_TimeSinceLastEvent; }
set { m_TimeSinceLastEvent = value; }
}
// Pretend property for serialization
[XmlElement("TimeSinceLastEvent")]
public long TimeSinceLastEventTicks
{
get { return m_TimeSinceLastEvent.Ticks; }
set { m_TimeSinceLastEvent = new TimeSpan(value); }
}
}
While this appears to work in my brief testing - is this the best way to achieve this?
Is there a better way to serialize a TimeSpan to and from XML?
This is only a slight modification on the approach suggested in the question, but this Microsoft Connect issue recommends using a property for serialization like this:
[XmlIgnore]
public TimeSpan TimeSinceLastEvent
{
get { return m_TimeSinceLastEvent; }
set { m_TimeSinceLastEvent = value; }
}
// XmlSerializer does not support TimeSpan, so use this property for
// serialization instead.
[Browsable(false)]
[XmlElement(DataType="duration", ElementName="TimeSinceLastEvent")]
public string TimeSinceLastEventString
{
get
{
return XmlConvert.ToString(TimeSinceLastEvent);
}
set
{
TimeSinceLastEvent = string.IsNullOrEmpty(value) ?
TimeSpan.Zero : XmlConvert.ToTimeSpan(value);
}
}
This would serialize a TimeSpan of 0:02:45 as:
<TimeSinceLastEvent>PT2M45S</TimeSinceLastEvent>
Alternatively, the DataContractSerializer supports TimeSpan.
The way you've already posted is probably the cleanest. If you don't like the extra property, you could implement IXmlSerializable, but then you have to do everything, which largely defeats the point. I'd happily use the approach you've posted; it is (for example) efficient (no complex parsing etc), culture independent, unambiguous, and timestamp-type numbers are easily and commonly understood.
As an aside, I often add:
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
This just hides it in the UI and in referencing dlls, to avoid confusion.
Something that can work in some cases is to give your public property a backing field, which is a TimeSpan, but the public property is exposed as a string.
eg:
protected TimeSpan myTimeout;
public string MyTimeout
{
get { return myTimeout.ToString(); }
set { myTimeout = TimeSpan.Parse(value); }
}
This is ok if the property value is used mostly w/in the containing class or inheriting classes and is loaded from xml configuration.
The other proposed solutions are better if you want the public property to be a usable TimeSpan value for other classes.
Combining an answer from Color serialization and this original solution (which is great by itself) I got this solution:
[XmlElement(Type = typeof(XmlTimeSpan))]
public TimeSpan TimeSinceLastEvent { get; set; }
where XmlTimeSpan class is like this:
public class XmlTimeSpan
{
private const long TICKS_PER_MS = TimeSpan.TicksPerMillisecond;
private TimeSpan m_value = TimeSpan.Zero;
public XmlTimeSpan() { }
public XmlTimeSpan(TimeSpan source) { m_value = source; }
public static implicit operator TimeSpan?(XmlTimeSpan o)
{
return o == null ? default(TimeSpan?) : o.m_value;
}
public static implicit operator XmlTimeSpan(TimeSpan? o)
{
return o == null ? null : new XmlTimeSpan(o.Value);
}
public static implicit operator TimeSpan(XmlTimeSpan o)
{
return o == null ? default(TimeSpan) : o.m_value;
}
public static implicit operator XmlTimeSpan(TimeSpan o)
{
return o == default(TimeSpan) ? null : new XmlTimeSpan(o);
}
[XmlText]
public long Default
{
get { return m_value.Ticks / TICKS_PER_MS; }
set { m_value = new TimeSpan(value * TICKS_PER_MS); }
}
}
You could create a light wrapper around the TimeSpan struct:
namespace My.XmlSerialization
{
public struct TimeSpan : IXmlSerializable
{
private System.TimeSpan _value;
public static implicit operator TimeSpan(System.TimeSpan value)
{
return new TimeSpan { _value = value };
}
public static implicit operator System.TimeSpan(TimeSpan value)
{
return value._value;
}
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
_value = System.TimeSpan.Parse(reader.ReadContentAsString());
}
public void WriteXml(XmlWriter writer)
{
writer.WriteValue(_value.ToString());
}
}
}
Sample serialized result:
<Entry>
<StartTime>2010-12-06T08:45:12.5</StartTime>
<Duration>2.08:29:35.2500000</Duration>
</Entry>
A more readable option would be to serialize as a string and use the TimeSpan.Parse method to deserialize it. You could do the same as in your example but using TimeSpan.ToString() in the getter and TimeSpan.Parse(value) in the setter.
Another option would be to serialize it using the SoapFormatter class rather than the XmlSerializer class.
The resulting XML file looks a little different...some "SOAP"-prefixed tags, etc...but it can do it.
Here's what SoapFormatter serialized a timespan of 20 hours and 28 minutes serialized to:
<myTimeSpan>P0Y0M0DT20H28M0S</myTimeSpan>
To use SOAPFormatter class, need to add reference to System.Runtime.Serialization.Formatters.Soap and use the namespace of the same name.
My version of the solution.
[DataMember, XmlIgnore]
public TimeSpan MyTimeoutValue { get; set; }
[DataMember]
public string MyTimeout
{
get { return MyTimeoutValue.ToString(); }
set { MyTimeoutValue = TimeSpan.Parse(value); }
}
Edit: assuming it is nullable:
[DataMember, XmlIgnore]
public TimeSpan? MyTimeoutValue { get; set; }
[DataMember]
public string MyTimeout
{
get
{
if (MyTimeoutValue != null)
return MyTimeoutValue.ToString();
return null;
}
set
{
TimeSpan outValue;
if (TimeSpan.TryParse(value, out outValue))
MyTimeoutValue = outValue;
else
MyTimeoutValue = null;
}
}
Timespan stored in xml as number of seconds, but it is easy to adopt, I hope.
Timespan serialized manually (implementing IXmlSerializable):
public class Settings : IXmlSerializable
{
[XmlElement("IntervalInSeconds")]
public TimeSpan Interval;
public XmlSchema GetSchema()
{
return null;
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString("IntervalInSeconds", ((int)Interval.TotalSeconds).ToString());
}
public void ReadXml(XmlReader reader)
{
string element = null;
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
element = reader.Name;
else if (reader.NodeType == XmlNodeType.Text)
{
if (element == "IntervalInSeconds")
Interval = TimeSpan.FromSeconds(double.Parse(reader.Value.Replace(',', '.'), CultureInfo.InvariantCulture));
}
}
}
}
There is more comprehensive example:
https://bitbucket.org/njkazakov/timespan-serialization
Look at Settings.cs.
And there is some tricky code to use XmlElementAttribute.
If you do not want any workarounds, use the DataContractSerializer class from System.Runtime.Serialization.dll.
using (var fs = new FileStream("file.xml", FileMode.Create))
{
var serializer = new DataContractSerializer(typeof(List<SomeType>));
serializer.WriteObject(fs, _items);
}
For data contract serialization I use the following.
Keeping the serialized property private keeps the public interface clean.
Using the public property name for serialization keeps the XML clean.
Public Property Duration As TimeSpan
<DataMember(Name:="Duration")>
Private Property DurationString As String
Get
Return Duration.ToString
End Get
Set(value As String)
Duration = TimeSpan.Parse(value)
End Set
End Property
For .NET6 and .NET7, TimeSpan serialization works out of the box. The format is the format for XSD "duration" datatype. So "14:30" is serialized to PT14H30M
For .NET Framework 4.8, this behavior can be activated with this switch:
AppContext.SetSwitch("Switch.System.Xml.EnableTimeSpanSerialization", true);
Try this :
//Don't Serialize Time Span object.
[XmlIgnore]
public TimeSpan m_timeSpan;
//Instead serialize (long)Ticks and instantiate Timespan at time of deserialization.
public long m_TimeSpanTicks
{
get { return m_timeSpan.Ticks; }
set { m_timeSpan = new TimeSpan(value); }
}

Is there a structure that handles Timeblocks?

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 ;)

Accessor with different set and get types?

Simple question, hopefully a simple answer:
I'd like to do the following:
private DateTime m_internalDateTime;
public var DateTimeProperty
{
get { return m_internalDateTime.ToString(); } // Return a string
set { m_internalDateTime = value; } // here value is of type DateTime
}
The above is just an example of what I'm trying to do. I'd like to have a public accessor to an internal variable of type x. I want the get that variable as a string, but set it using something of type x.
Is this possible?
--edit--
I just realized I could do something like:
private DateTime m_internalDateTime;
public object DateTimeProperty
{
get { return m_internalDateTime.ToString(); } // Return a string
set { m_internalDateTime = (DateTime)value; } // here value is of type DateTime
}
But then, let say I use type y instead of a "string" as my 'get' type. If I want to use "DateTimeProperty" else where in my code, I'd have to cast it.
No. You can obviously add the .ToString() in the calling code, but you can't do what you propose without different names like this:
private DateTime m_internalDateTime;
public DateTime SetDateTime { set { m_internalDateTime = value; } }
public string GetDateTime { get { return m_internalDateTime.ToString(); } }
Or, even better to use methods instead of properties (as noted in the comments):
private DateTime m_internalDateTime;
public void SetDateTime(DateTime dateTime) { m_internalDateTime = dateTime; }
public string GetDateTime() { return m_internalDateTime.ToString(); }
Keep in mind that var is for implicitly, compile-time typed variables, not dynamic variables.
Definitely do not do what you noted in your edit. It introduced a break in convention, possible performance implications (albeit slight), and significant localization problems.
As a property, no this is not possible. You could make Get and Set methods that are of different types, but for a property the types must be the same.
EDIT:
While:
private DateTime m_internalDateTime;
public object DateTimeProperty
{
get { return m_internalDateTime.ToString(); } // Return a string
set { m_internalDateTime = (DateTime)value; } // here value is of type DateTime
}
is syntactically correct, will compile and allows you to accept DateTime as input and return a string, this would not be a good plan. It works, but it makes you and anyone accessing this code, perform unneeded validation. Additionally, it is vulnerable to another developer in the future, not knowing, or realizing the implicit rules, for which you have lost compile time safety. Additionally, its hardly any more code to create either two properties, or two methods that accomplish the same goal, in a strongly typed manner.
Personally, I would recommend using two methods (see Jeff Yates comment for a good explanation as to why).
private DateTime m_internalDateTime;
public string GetDateTime()
{
return m_internalDateTime.ToString();
}
public void SetDateTime(DateTime dateTime)
{
m_internalDateTime = dateTime;
}
Not that way, but you can certainly have a second property that accesses the m_internalDateTime field.
public string DateTimeString
{
get { return m_internalDateTime.ToString(); }
}
Maybe that helps
public class TDecimal
{
private decimal? m_value;
public bool HasValue { get { return m_value.HasValue; } }
public decimal Value { get { return m_value.Value; } }
public static implicit operator TDecimal(string a_value)
{
decimal d;
if (decimal.TryParse(a_value, out d))
{
return new TDecimal() {m_value = d};
}
return new TDecimal() {m_value = null};
}
public static implicit operator decimal(TDecimal a_value)
{
if(a_value.HasValue)
{
return a_value.Value;
}
throw new ArgumentNullException("a_value");
}
}
public class A
{
public TDecimal Prop { get; set; }
}
A a = new A();
a.Prop = "123";
if (a.Prop.HasValue)
{
decimal d = a.Prop;
}
Simple answer no, to your outside code your property will behave the exact way that a field would, you can't have a property having different set/get types just as you couldn't have a filed be set with a type and when you request it's value get a different type back.
how about:
private DateTime intDT;
public string DateTimeProperty
{
get { return intDT.ToString(); } // Return a string
set
{
DateTime dt;
if (DateTime.TryParse(value, out dt))
intDT = dt;
else throw new ArgumentException(string.Format(
"{0} cannot be converted to a DateTime.", value);
}
}

Categories

Resources