Marshal.StructureToPtr <-> PtrToStructure rounds DateTime field - c#

The structure
public struct Tick : IEquatable<Tick>
{
public DateTime date;
public decimal price;
public int volume;
public Tick(DateTime date, decimal price, int volume)
{
this.date = date;
this.price = price;
this.volume = volume;
}
public override bool Equals(object obj)
{
var other = (Tick)obj;
return this.date == other.date && this.price == other.price && this.volume == other.volume;
}
public bool Equals(Tick other)
{
return this.date == other.date && this.price == other.price && this.volume == other.volume;
}
}
is changed in this test:
[Test]
public void MarshalDoesntRoundsDateTime() {
for (int i = 0; i < 1000; i++)
{
var now = new Tick(DateTime.Now.AddSeconds(i), i, i);
var now2 = now;
var ticks = new Tick[1];
unsafe
{
fixed (Tick* ptr = &ticks[0])
{
Marshal.StructureToPtr(now2, (IntPtr)ptr, false);
now2 = (Tick)Marshal.PtrToStructure((IntPtr)ptr, typeof(Tick));
Assert.AreEqual(now.date.Ticks, now2.date.Ticks);
}
}
}
}
Expected: 635719676058860752
But was: 635719676058860000
What is going on? Why DateTime is rounded after marshalling? Is this documented somewhere?

Marshal.StructureToPtr() is intended to marshal data for unmanaged code. There is are multiple "standards" for dates in native code, none that are close in range and accuracy to DateTime. The CLR designers went for the COM interop standard, also exposed by DateTime.ToOADate().
As you can tell from the Reference Source, it can be no more accurate than 1 msec. DateTime is accurate to 0.1 usec. Inevitably the last 4 digits you are looking at must be 0.
It is not clear why you are doing this or why it matters. Guessing, do keep in mind that Marshal.StructureToPtr() only seems like an attractive way to serialize .NET data.

The true error is that DateTime shouldn't be marshalable... If you try to Marshal it directly you get an ArgumentException.
If you really really want to Marshal a DateTime (and I don't even want to know why, considering it is a semi-proprietary format of .NET), you could:
public long date;
public DateTime Date
{
get
{
return DateTime.FromBinary(date);
}
set
{
date = value.ToBinary();
}
}

Related

Action method in c#

I just want him to give me what has changed at the entrance. When I want to get the same value to the input of the select method, I want to get the same values in the action output, not the whole properties class WeatherForecast.
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
public void method(){
Select(d=>
{
d.Summary = "dasd";
d.TemperatureC = 25;
});}
private void Select(Action<WeatherForecast> func)
{
var result = new WeatherForecast();
func(result);
foreach (var item in result.GetType().GetProperties())
{
RaisePropertyChanged(item.Name);
}
var ss = func;
}
'''
That isn't a thing that you can do trivially, basically. There are three general approaches you could use here:
add change tracking to the WeatherForecast type, so it knows what has changed (usually with some kind of reset method to mark everything unchanged, and code in each setter to record individual properties as changed)
use an external change tracker which records the original state in a shapshot somehow, then later: compares that against the current value
if using an Expression-tree, interpret the proposed changes there - however: the C# compiler cannot interpret the code in the question as an Expression-tree (even though an Expression-tree of this can be generated)
Of these, IMO only the first is even remotely viable here unless you have a lot of spare time. Something like:
private int _dirtyFlags;
public void ResetAllChanges() => _dirtyFlags = 0;
private DateTime _date;
public DateTime Date
{
get => _date;
set
{
if (_date != value) _dirtyFlags |= 1 << 0;
_date = value;
}
}
// this name is a convention used by some tools; but this
// could also be IsDateChanged, for example
public bool ShouldSerializeDate() => (_dirtyFlags & (1 << 0)) != 0;
private int _temperatureC;
public int TemperatureC
{
get => _temperatureC;
set
{
if (_temperatureC != value) _dirtyFlags |= 1 << 1;
_temperatureC = value;
}
}
public bool ShouldSerializeTemperatureC() => (_dirtyFlags & (1 << 1)) != 0;
etc; this is clearly quite a lot of work, and doesn't generalize much.

Why can only auto-implemented properties can have initializers in C#?

I get the "only auto-implemented properties can have initializers in C#" error when trying to do the following:
public int Precision
{
get { return Precision; }
set
{
if (value < 0)
Precision = 0;
else if (value > 15)
Precision = 15;
else
Precision = value;
}
} = 12;
Why is this not allowed?
Pretty sure that is not really how you use get and set. Plus your get suffers from self reference. I think this is what you want:
private int _precision = 12;
public int Precision {
get => _precision;
set {
if (value < 0)
_precision = 0;
else if (value > 15)
_precision = 15;
else
_precision = value;
}
}
Well, an auto-property is just syntactic sugar for a property that gets and sets an automatically created backing-field. So the following two code-segments are similar:
public int Precision { get; set; }
and
public int Precision
{
get { return <Precision>k__BackingField; }
set { <Precision>k__BackingField = value; }
}
However when you create some own logic within your property, thereĀ“s no such thing as an automatically backing-field. In fact you could even do the following without any backing-field:
set { Console.WriteLine(); }
An initial value however is resolved to the following constructor:
MyClass()
{
this.<Precision>k__BackingField = myValue;
}
However when there is no such backing-field, what should the compiler do here?

How to eliminate the conditional in my accumulator?

Given this code:
private static IObservable<Stock> ToStock(this IObservable<decimal> prices, string symbol)
{
return prices.Scan(
default(Stock),
(previous, price) => previous == default(Stock)
? new Stock(symbol, price)
: previous.Change(price));
}
// The signature for Stock.Change() looks like this. Stock is an immutable class.
// public Stock Change(decimal newCurrentPrice)
I would like to eliminate the check previous == default(Stock) that is happening on every call to the accumulator. What I have is behavior that is different for the first item vs the rest. I'm not sure how to express that simply using LINQ for Rx.
EDIT. Here's the code for Stock, which might help explain why I can't give it a sentinel value for price.
public class Stock
{
private readonly decimal _current;
private readonly decimal _dayHigh;
private readonly decimal _dayLow;
private readonly decimal _dayOpen;
private readonly decimal _lastChange;
private readonly string _symbol;
public Stock(string symbol, decimal price)
{
if (symbol == null) throw new ArgumentNullException("symbol");
if (price <= 0) throw new ArgumentOutOfRangeException("price", "Price must be greater than zero.");
_symbol = symbol;
_current = _dayOpen = _dayLow = _dayHigh = price;
}
private Stock(Stock original, decimal newCurrent)
{
if (original == null) throw new ArgumentNullException("original");
_symbol = original.Symbol;
_current = newCurrent;
_dayOpen = original.DayOpen;
_dayHigh = Math.Max(newCurrent, original.DayHigh);
_dayLow = Math.Min(newCurrent, original.DayLow);
_lastChange = newCurrent - original.Current;
}
public string Symbol { get { return _symbol; } }
public decimal Current { get { return _current; } }
public decimal LastChange { get { return _lastChange; } }
public decimal DayOpen { get { return _dayOpen; } }
public decimal DayLow { get { return _dayLow; } }
public decimal DayHigh { get { return _dayHigh; } }
public decimal DayChange { get { return Current - DayOpen; } }
public double DayChangeRatio { get { return (double) Math.Round(DayChange/Current, 4); } }
public Stock Change(decimal newCurrent)
{
return newCurrent == Current
? this
: new Stock(this, newCurrent);
}
}
I came up with this solution:
private static IObservable<Stock> ToStock2(this IObservable<decimal> prices, string symbol)
{
Func<Stock, decimal, Stock> accumulator = (_, firstPrice) =>
{
accumulator = (previous, price) => previous.Change(price);
return new Stock(symbol, firstPrice);
};
return prices.Scan(default(Stock), (previous, price) => accumulator(previous, price));
}
It uses a self-mutating Func variable to change the behavior during its first invocation, but a quick test (ran with 0.5 million prices) shows that it performs 2-3% slower than the original method, and the code is much less clear. It seems .NET is more efficient at doing the equality comparer for every item, vs. calling a second Func for every item. I'm not sure if there's anyway to optimize this so that it performs better enough than the original to justify the lessened clarity.
You can do this:
public static partial class ObservableExtensions
{
public static IObservable<Stock> ToStock(this IObservable<decimal> prices, string symbol)
{
return Observable.Create<Stock>(o =>
{
Stock lastStock;
Action<decimal> action = null;
action = price => {
lastStock = new Stock(symbol, price);
action = newPrice =>
{
lastStock = lastStock.Change(newPrice);
o.OnNext(lastStock);
};
o.OnNext(lastStock);
};
return prices.Subscribe(p => action(p), o.OnError, o.OnCompleted);
});
}
}
Compared to Jim's answer, I'm not sure if mine is any better; it's a similar idea but it avoids calling Scan which may avoid some hops.
My flakey performance tests showed this runs no worse than the original - but no better either. I ran it a few times with 100,000,000 prices and they took within 1% of each other with each winning roughly half the time. There was no statistically significant difference.
I would take this with a pinch of salt though, as this is on my home PC and not in a lab environment, not run for very long and with god knows what other services installed.
HOWEVER... I did get a seemly significant 3% improvement by rewriting the private constructor to not do the Math.Max/Min calculation redundantly, and to bypass the properties and access the fields directly - and I'm sure there's further mileage to be explored such as removing Change and using public fields:
private Stock(Stock original, decimal newCurrent)
{
if (original == null) throw new ArgumentNullException("original");
_symbol = original._symbol;
_current = newCurrent;
_dayOpen = original._dayOpen;
if(newCurrent > original._dayHigh)
{
_dayHigh = newCurrent;
_dayLow = original._dayLow;
}
else
{
_dayHigh = original._dayHigh;
_dayLow = newCurrent;
}
_lastChange = newCurrent - original._current;
}
On general performance - with a lot of prices, there is going to be a fair amount of GC pressure with this approach. I've had success in the past with using a pool of Stock instances in a ring buffer implemented with an array to reduce garbage collection.
return prices.Skip(1)
.Scan(new Stock(symbol, prices.First()),
(previous, price) => previous.Change(price));
Does this fix your problem of side-effects?
I would prefer to introduce some kind of polymorfism. You can introduce special case of Stock just for seed purpose:
public class Stock {
// same implementation as yours but make the Change method virtual
public static Stock Seed(string symbol) {
return new StockSeed(symbol);
}
class StockSeed : Stock {
public StockSeed(string symbol) {
_symbol = symbol;
}
public override Stock Change(decimal newCurrent) {
return new Stock(Symbol, newCurrent)
}
}
}
Then you can simplify the reactive code to:
static IObservable<Stock> ToStock(this IObservable<decimal> prices, string symbol)
{
return prices.Scan(Stock.Seed(symbol), (prev, price) => prev.Change(price));
}

Visual C# - Get accessor method returns 0 for value

I'm trying to pass method values along between forms. As a result, I've made the methods whose data I want to pass along static. Since I'm using non-static text boxes to gather user input, I've also made public property methods to parse the input from the user, store its value in a public class-level static variable, and return the value to the static methods which call the variable.
public static int laborHours;
public int lHoursB
{
get
{
return laborHours;
}
set
{
laborHours = int.Parse(lHours.Text);
}
}
private static decimal laborMethod(decimal laborTotal)
{
const decimal laborCharge = 50M;
decimal labor = 0;
labor = laborCharge * laborHours;
return labor;
}
public static decimal amountCharged;
public decimal amount
{
get
{
return amountCharged;
}
set
{
amountCharged = int.Parse(amtBox.Text);
}
}
public static int numberOfParts;
public int partsNumber
{
get
{
return numberOfParts;
}
set
{
numberOfParts = int.Parse(partsBox.Text);
}
}
private static decimal subtotalMethod(decimal subTotal)
{
decimal subtotal = 0;
subtotal = amountCharged * numberOfParts;
return subtotal;
}
private static decimal subtotal2Method(decimal subtotalTwo)
{
decimal labor = 0;
decimal subtotal = 0;
labor = laborMethod(labor);
subtotal = subtotalMethod(subtotal);
subtotalTwo = subtotal + labor;
return subtotalTwo;
}
private static decimal taxMethod(decimal salesTax)
{
const decimal tax = .08M;
decimal sTax = 0;
decimal sub = 0;
sub = subtotalMethod(sub);
sTax = sub * tax;
return sTax;
}
The compiler checks everything out as a clean compile, but there's a logic error here I can't seem to find. When I run a simple test with the program, every text box returns a "0".
Help, please?
Your properties are back to front compared to the normal way they are written. I suggest you write them like this instead:
public int lHoursB
{
get
{
int result = 0;
int.TryParse(lHours.Text, out result);
return result;
}
set
{
lHours.Text = value.ToString();
}
}
Then you can do:
lHoursB = 10;
which will set the lHours textbox to "10". I have used TryParse and not Parse, as the latter will throw a FormatException if it cannot parse the string; you may prefer to have an exception, in which case use Parse. Also you should use Decimal.Parse/TryParse and not Int32.Parse for amount, which is a decimal and not an int. Finally, you can specify a culture in the int.ToString call, if you want to format the int for a specific culture (see Int32.ToString()).

Get a range of dates given an interval and step

Edit
It looks like creating a table that holds the DateTimes by minutes to join against would make the most sense. 100 years worth of minutes is ~52M rows. Indexed by the Ticks should make the query run pretty fast. It now becomes
Thanks for the feedback everyone!
I have a class called Recurrence that looks like this:
public class Recurrence
{
public int Id { get; protected set; }
public DateTime StartDate { get; protected set; }
public DateTime? EndDate { get; protected set; }
public long? RecurrenceInterval { get; protected set; }
}
It is an entity framework POCO class. There are two things I want to do with this class all with standard query operators. (So that the query runs entirely server side).
First I want to create a query that returns all the dates from the start date to the end date inclusive with the given recurrence interval. The iterative function is simple
for(i=StartDate.Ticks; i<=EndDate.Ticks; i+=RecurrenceInterval)
{
yield return new DateTime(i);
}
Enumerable.Range() would be an option but there is no long version of Range. I'm thinking my only option here is Aggregate but I'm still not very strong with that function.
Finally once I have that query working, I want to return the values from there that are within a time window i.e. between a different start and end date. That is easy enough to do using SkipWhile/TakeWhile.
Here's how I could do it if DateTime.Ticks was an int
from recurrence in Recurrences
let range =
Enumerable
.Range(
(int)recurrence.StartDate.Ticks,
recurrence.EndDate.HasValue ? (int)recurrence.EndDate.Value.Ticks : (int)end.Ticks)
.Where(i=>i-(int)recurrence.StartDate.Ticks%(int)recurrence.RecurrenceLength.Value==0)
.SkipWhile(d => d < start.Ticks)
.TakeWhile(d => d <= end.Ticks)
from date in range
select new ScheduledEvent { Date = new DateTime(date) };
I guess what I need is an implementation of LongRange that could execute over an EF Query.
Here's the function that yields the intersection of the Recurrence points and a specified subinterval:
public class Recurrence
{
public int Id { get; protected set; }
public DateTime StartDate { get; protected set; }
public DateTime? EndDate { get; protected set; }
public long? RecurrenceInterval { get; protected set; }
// returns the set of DateTimes within [subStart, subEnd] that are
// of the form StartDate + k*RecurrenceInterval, where k is an Integer
public IEnumerable<DateTime> GetBetween(DateTime subStart, DateTime subEnd)
{
long stride = RecurrenceInterval ?? 1;
if (stride < 1)
throw new ArgumentException("Need a positive recurrence stride");
long realStart, realEnd;
// figure out where we really need to start
if (StartDate >= subStart)
realStart = StartDate.Ticks;
else
{
long rem = subStart.Ticks % stride;
if (rem == 0)
realStart = subStart.Ticks;
else
// break off the incomplete stride and add a full one
realStart = subStart.Ticks - rem + stride;
}
// figure out where we really need to stop
if (EndDate <= subEnd)
// we know EndDate has a value. Null can't be "less than" something
realEnd = EndDate.Value.Ticks;
else
{
long rem = subEnd.Ticks % stride;
// break off any incomplete stride
realEnd = subEnd.Ticks - rem;
}
if (realEnd < realStart)
yield break; // the intersection is empty
// now yield all the results in the intersection of the sets
for (long t = realStart; t <= realEnd; t += stride)
yield return new DateTime(t);
}
}
You could create your own date range method
public static class EnumerableEx
{
public static IEnumerable<DateTime> DateRange(DateTime startDate, DateTime endDate, TimeSpan intervall)
{
for (DateTime d = startDate; d <= endDate; d += intervall) {
yield return d;
}
}
}
Then query with
var query =
from recurrence in Recurrences
from date in EnumerableEx.DateRange(recurrence.StartDate,
recurrence.EndDate ?? end,
recurrence.RecurrenceInterval)
select new ScheduledEvent { Date = date };
This assumes that RecurrenceInterval is declared as TimeSpan and end as DateTime.
EDIT: Would this version restrict the recurrences on the server side as you excpect?
var query =
from recurrence in Recurrences
where
recurrence.StartDate <= end &&
(recurrence.EndDate != null && recurrence.EndDate.Value >= start ||
recurrence.EndDate == null)
from date in EnumerableEx.DateRange(
recurrence.StartDate,
recurrence.EndDate.HasValue && recurrence.EndDate.Value < end ? recurrence.EndDate.Value : end,
recurrence.RecurrenceInterval)
where (date >= start)
select new ScheduledEvent { Date = date };
Here the returned recurrences already take in account the start and the end date, thus not returning obsolete recurrences. EnumerableEx.DateRange has no effect on the first part of the query.

Categories

Resources