Reconciling properties of structs and DateTime - c#

I have been looking through the DateTime structure and I am slightly confused.
My understanding with structs is that you cannot assign 'default values' of fields. If the default constructor of a struct is used (which is not something that you can control), then any fields will be initialized using the default values of their value type.
This is all good and well, but why then is the default value of the 'Days' property of a DateTime equal to 1? How do they pull that off?
William

You need to understand the difference between fields and properties.
The fields are all initialized to 0, but the properties can do what they like with those fields. Sample:
public struct Foo
{
private readonly int value;
public Foo(int value)
{
this.value = value;
}
public int ValuePlusOne { get { return value + 1; } }
}
...
Foo foo = new Foo(); // Look ma, no value! (Defaults to 0)
int x = foo.ValuePlusOne; // x is now 1
Now obviously DateTime is a smidge more complicated than this, but it gives the right idea :) Imagine what "A DateTime with the field explicitly set to 0" would mean... the "default" DateTime just means exactly the same thing.

Jon Skeet is right it's all about the difference between fields and other members. One could really make a "date time" like this:
struct MyDateTime
{
// This is the only instance field of my struct
// Ticks gives the number of small time units since January 1, 0001, so if Ticks is 0UL, the date will be just that
readonly ulong Ticks;
// here goes a lot of instance constructors,
// get-only instance properties to show (components of) the DateTime in a nice way,
// static helper methods,
// and lots of other stuff, but no more instance fields
...
}
So in reality, MyDateTime is just a wrapped ulong with an interpretation, and a lot of nice ways to show and manipulate that ulong.

Related

How to use properties with an integral overflow (byte)?

I am fairly new to programming and C#, and I am creating a game using C# 9.0 in which all instances of Entity have certain stats. I want to be able to change their private data fields using properties, though I'm not entirely sure how properties work. I know they are useful in encapsulation as getters and setters.
Context:
I am trying to optimize code and decrease memory usage where possible
The byte field str should be variable (through events, training, etc.), but have a "ceiling" and "floor"
If dog.str = 253, then dog.Str += 5; should result in dog.str being 255
If dog.str = 2, then dog.Str -= 5; should result in dog.str being 0
private byte str;
public short Str
{
get => str;
set
{
if (value > byte.MaxValue) str = byte.MaxValue; //Pos Overflow
else if (value < byte.MinValue) str = byte.MinValue; //Neg Overflow
else str = (byte)value;
}
}
Questions:
Since the property is of datatype Short, does it create a new private backing field that consumes memory? Or is value/Str{set;} just a local variable that later disappears?
Does the property public float StrMod {get => (float)(str*Effects.Power);} create a backing field? Would it be better to just create a method like public float getStrMod() instead?
Is this code optimal for what I'm trying to achieve? Is there some better way to do this, considering the following?
If for some reason the Short overflowed (unlikely in this scenario, but there may be a similar situation), then I would end up with the same problem. However, if extra memory allocation isn't an issue, then I could use an int.
The {get;} will return a Short, which may or may not be an issue.
Question 1:
No it doesn't, its backing field is str.
Question 2:
Profile your code first instead of making random changes in hope to reduce memory usage.
"Premature optimization is the root of all evil", do you really have such issues at this point ?
Personally I'd use int and use same type for property and backing field for simplicity.
This would avoid wrapping such as assigning 32768 which would then result as -32768 for short.
Side note, don't think that using byte necessarily results in 1 byte, if you have tight packing requirements then you need to look at StructLayoutAttribute.Pack.
Other than that I see nothing wrong with your code, just get it to work first then optimize it!
Here's how I'd write your code, maybe you'll get some ideas from it:
class Testing
{
private int _value;
public int Value
{
get => _value;
set => _value = Clamp(value, byte.MinValue, byte.MaxValue);
}
private static int Clamp(int value, int min, int max)
{
return Math.Max(min, Math.Min(max, value));
}
}
EDIT:
Different scenarios:
class Testing
{
private int _value1;
public int Value1 // backing field is _value1
{
get => _value1;
set => _value1 = value;
}
public int Value2 { get; set; } // adds a backing field
public int Value3 { get; } // adds a backing field
public int Value4 => 42; // no backing field
}
As you might have guessed, properties are syntactic sugar for methods, they can do 'whatever' under the hood compared to a field which can only be assigned a value to.
Also, one difference with a method is that you can browse its value in the debugger, that's handy.
Suggested reading:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
Finally, properties are expected to return quickly, else write a method, and possibly async if it's going to take a while (advantage to method in this case as properties can't be async).
#aybe answer covers main thing about you question. I would like to add additional info to your 2nd question. You should consider on which platform you write application. There is a word term:
In computing, a word is the natural unit of data used by a particular
processor design. A word is a fixed-sized piece of data handled as a
unit by the instruction set or the hardware of the processor. The
number of bits in a word (the word size, word width, or word length)
is an important characteristic of any specific processor design or
computer architecture.
If processor has 64 bit word, then every variable which type is less than 64 bits will still occupy 64 bits in memory. Keep in mind that variable of given type will be handled as given type and size in memory doesn't impact range, overflow or underflow - arithmetic will be processed for given type.
In short - if you have 64-bit desktop processor and you will use only short variables, then you will not observe any memory savings in comparison to declaring int variables.

What's so special about properties?

I have the basics down with properties, but I don't see a real use for them. Doesn't it just return the value of an equation? I mean there is no point in using a property if you could just write down a simple equation for it.
For example:
int currentValue;
public int CurrentValue
{
get { return currentValue; }
set { currentValue = value; }
}
Is the same thing as just:
currentValue;
Another example:
int currentValue;
public int CurrentValue
{
get { return currentValue * 5; }
set { currentValue = value; }
}
Is the same thing as:
currentValue = currentValue * 5;
In your first example, Public Fields versus Automatic Properties is a good answer. Basically, you should use always properties instead of fields for non-private things. This lets you do things like modify the code later without breaking things, and make a private set. Properties can also do things like notify code when they're changed or provide default or calculated values easily. And you can use auto-properties to cut down on extraneous code:
public int CurrentValue { get; set; }
Your second example is not a good use of properties, since it breaks the assumptions of how properties work. E.g. if I set the property to 3 and no exception is thrown, I'd expect it to be 3 when I get it, not 15. currentValue = currentValue * 5;, which could make sense working with a field, property, or local variable, makes the value 5 times larger. Maybe you meant something like this:
int currentBackingValue;
public int CurrentValue
{
get { return currentBackingValue * 5; }
}
Without a set, this can work nicely, and without breaking any conventions and assumptions: CurrentValue is calculated based on currentBackingValue.
(as an aside, you should note that the getters and setters of a property are, in fact, methods, just used with a field-like syntax to replace something like Java's getX/setX standard)
Getters and setters properties are handy if you want to add some extra functionality to your code, centralizing your function so you can change it only in one place. You almost never know when you're going to have to change something, but you can prepare.
This, along with the concepts of encapsulation and information hiding, are basic OOP concepts but very important...
V E R Y I M P O R T A N T
Don't underestimate this tremendous power D:
Its so... powerful...
Properties are also used in a number of other .NET technologies, WPF doesn't work without them (with a PropertyChanged event invoke in the setter) and WCF uses them extensively in data contracts.
Especially relating to WPF, the power of properties is that both the "get" and "set" fields are functions and so can do lots of things besides just returning or setting the backing private member. This comes in handy more times than you may think.
Example property (for WPF)
public String UIDisplayedString
{
get { return _member; }
set
{
_member = value;
PropertyChanged(new PropertyChangedEventArgs("UIDisplayedString"));
}

Casting string value to enumerated value C#

I have a class MyClass which has
public enum Days{Mon, Tue, Wed}
and then a field
public Days dayOfWeek;
From another class in my solution I have a string (myString) value of either 0, 1 or 2. I want to set an instance of MyClass's (called myClassInstance) field dayOfWeek equal to myStringvalue such that 0 means Mon, 1 means Tue...
I have tried
myClassInstance.dayOfWeek = Convert.ToInt32(myString)
and
myClassInstance.dayOfWeek = (int) myString
but neither work. I'm sure this is straightforward. Why don't these techniques work?
Try
string s = "0";
Days day = (Days)Enum.Parse(typeof(Days), s);
or
string s = "0";
Days day;
if(!Enum.TryParse(s, out day)) {
// error handling
}
to gracefully handle the case where s can't be parsed to an instance of Days.
This works per the documentation for Enum.Parse which states
Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.
Additionally, you can check if the instance of string actually represents a value defined by the enum via
string s = "3";
bool defined = Enum.IsDefined(typeof(Days), s);
// defined is false
Enum.Parse will blindly parse s in this case, even though it doesn't represent a value defined by the enum Days and the cast from the result of Enum.Parse to Days will not fail.
Moreover, there is a built-in enum that represents the days of the week. This enum is System.DayOfWeek. I would suggest using this.
Finally, if for some reason you can't use System.DayOfWeek, you should at a minimum rename your enum to Day instead of Days (remove the pluralization). Only enums that represent flags should be pluralized. Note that the variable day above represents a day, and it does not represent days. This is why you should rename the enum to Day. This is consistent with the naming conventions that most C# and .NET programmers use.
You just need to cast the int to the Days enum after converting it:
myClassInstance.dayOfWeek = (Days)Convert.ToInt32(myString);
You can also use Enum.TryParse (if you're in .NET 4) or Enum.Parse. Depending on how much your trust the incoming data, you may also want to call Enum.IsDefined to make sure that the integer is a valid value of Days (otherwise, in all of these cases, you'll have an instance of Days that doesn't correspond to any of your named values).
Days dayOfWeek;
if (!Enum.TryParse(myString, out dayOfWeek)) {
dayOfWeek = Days.Mon; // or some other default, or throw
}
myClassInstance.dayOfWeek = dayOfWeek;
Or
myClassInstance.dayOfWeek = (Days)Enum.Parse(typeof(Days), myString);
In addition, as others have mentioned, you may want to consider using the built-in DayOfWeek enum instead of your custom version, if it matches what you really want.
Also, as others have mentioned again, even if it doesn't, Day is a better name based on the .NET naming guidelines, since it isn't a Flags enum.
Try
myClassInstance.dayOfWeek = (Days)int.Parse(myString);
Do you know there is already an Enum that you can resuse called DayOfWeek (http://msdn.microsoft.com/en-us/library/system.dayofweek.aspx)
Try:
Days d = (Days)Enum.Parse(typeof(Days), myString);
A more complete example is here.
You need to cast the int to Days:
myClassInstance.dayOfWeek = (Days)Convert.ToInt32(myString);
What you want to do is cast the string to an int (or tryparse if you want to do it in a nice way)
Then use the Following code to set the enum value:
(Days)Enum.ToObject(typeof(Days), intValue);
This should work
myClassInstance.dayOfWeek = Enum.Parse(typeof(Days), myString);
Enump.Parse

What is main use of Enumeration?

What is main use of Enumeration in c#?
Edited:-
suppose I want to compare the string variable with the any enumeration item then how i can do this in c# ?
The definition in MSDN is a good place to start.
An enumeration type (also named an
enumeration or an enum) provides an
efficient way to define a set of named
integral constants that may be
assigned to a variable.
The main benefit of this is that constants can be referred to in a consistent, expressive and type safe way.
Take for example this very simple Employee class with a constructor:
You could do it like this:
public class Employee
{
private string _sex;
public Employee(string sex)
{
_sex = sex;
}
}
But now you are relying upon users to enter just the right value for that string.
Using enums, you can instead have:
public enum Sex
{
Male = 10,
Female = 20
}
public class Employee
{
private Sex _sex;
public Employee(Sex sex)
{
_sex = sex;
}
}
This suddenly allows consumers of the Employee class to use it much more easily:
Employee employee = new Employee("Male");
Becomes:
Employee employee = new Employee(Sex.Male);
Often you find you have something - data, a classification, whatever - which is best expressed as one of several discrete states which can be represented with integers. The classic example is months of the year. We would like the months of the year to be representable as both strings ("August 19, 2010") and as numbers ("8/19/2010"). Enum provides a concise way to assign names to a bunch of integers, so we can use simple loops through integers to move through months.
Enums are strongly typed constants. Enumerations are special sets of named values which all maps to a set of numbers, usually integers. They come in handy when you wish to be able to choose between a set of constant values, and with each possible value relating to a number, they can be used in a wide range of situations. As you will see in our example, enumerations are defined above classes, inside our namespace. This means we can use enumerations from all classes within the same namespace.
using System;
namespace ConsoleApplication1
{
public enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
class Program
{
static void Main(string[] args)
{
Days day = Days.Monday;
Console.WriteLine((int)day);
Console.ReadLine();
}
}
}
Enumeration (Enum) is a variable type. We can find this variable type in C, C# and many other languages.
Basic Idea for Enum is that if we have a group of variable of integer type (by default) then instead of using too much int values just use a Enum. It is efficient way. Let suppose you want to write rainbow colours then you may write like this:
const int Red = 1;
const int Orange = 2;
const int Yellow = 3;
const int Green = 4;
const int Blue = 5;
const int Indigo = 6;
const int Violet = 7;
here you can see that too many int declarations. If you or your program by mistake change the value of any integer varialbe i.e. Violet = 115 instead of 7 then it will very hard to debug.
So, here comes Enum. You can define Enum for any group of variables type integers. For Enum you may write your code like this:
enum rainBowColors
{
red=1,
orange=2,
yellow=3,
green,
blue=8,
indigo=8,
violet=16)
};
rainBowColors is a type and only other variables of the same type can be assigned to this. In C#/C++ you need to type casting while in C you do not to type cast.
Now, if you want to declare a variable of type rainBowColors then in C
enum rainBowColors variableOne = red;
And in C# / C++ you can do this as:
rainBowColors variableOne = red;
There are two meanings of enumeration in C#.
An enumeration (noun) is a set of named values. Example:
public enum Result {
True,
False,
FileNotFound
}
Enumeration (noun form of the verb enumerate) is when you step through the items in a collection.
The IEnumerable<T> interface is used by classes that provide the ability to be enumerated. An array is a simple example of such a class. Another example is how LINQ uses it to return results as enumerable collections.
Edit:
If you want to compare a string to an enum value, you either have to parse the string to the enum type:
if ((Result)Enum.Parse(typeof(Result), theString) == Result.True) ...
or convert the enum value to a string:
if (theString == Result.True.ToString()) ...
(Be careful how you compare the values, depending on whether you want a case sensetive match or not.)
If you want to enumerate a collection and look for a string, you can use the foreach command:
foreach (string s in theCollection) {
if (s == theString) {
// found
}
}
Another advantage of using Enum is that in case of any of the integer value needs to be changed, we need to change only Enum definition and we can avoid changing code all over the place.
An enumeration type (also named an enumeration or an enum) provides an efficient way to define a set of named integral constants that may be assigned to a variable.
http://msdn.microsoft.com/en-us/library/cc138362.aspx
Enumeration (ENUM)
An enum is a value type with a set of related named constants often referred to as an enumerator list. The enum keyword is used to declare an enumeration. It is a primitive data type, which is user defined.
Enums type can be integer (float, int, byte, double etc.). But if you used beside int it has to be cast.
enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };
enum Months : byte { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec };
Lets Take an Example we are taking normal constant in a class like
int a=10;
by mistakely we assign new value to that variable in that same class like
a=20;
then we will get wrong data when we want access them.
enum provide secure way of accessing constant.
Also if we have many feild constant in a class we had to memorize them if we want to use them in a class.
but enum contains group of related name constant, if we want to access the constant then only we had to memorize enum name.
Enumerations in my experience have worked in very specific cases and should be used when you absolutely need to maintain this in your application. Problems come into play with Enums when you are working with multiple developers and some new developer comes on to a project and can adds a enum to the application no errors everything builds but then you have another full stack developer that maintains this same list in a lookup table in a different order. Kaboom!!!!
Burned way to many times with that one even if not intentional. Rule of thumb don't maintain a list of enums in a app over 5 or 6 items. If higher you might as well store them in a lookup table in the DB of your choice.

How to implement Year for movies in C#?

I am writing a Movie class that will have a Year property. Should it be just an int, or should I use a DateTime object?
Just wondering the best option. Maybe I am missing something.
I would probably use an int for simplicity, and make sure that in the setter you verify that the year value makes sense.
Alternatively, you can create a type to just represents years - this would make sure you don't misuse the year as a regular integral value. This gets complicated though, especially if you want to start overloading operators to support year addition and subtraction. Unless you really need this extra level of type safety, I would stick with an int.
If it's only going to be a year value, then int will be simpler. You could also consider just saving the release date as a DateTime, and get the year from that (instead of having a year attribute).
If it's only ever going to be the year then an int (or custom type) would do.
If you want to store the month as well then I'd use a DateTime.
The Agile mantra - YAGNI (You Ain't Gonna Need It) - would suggest an int until you want more information and then refactor into a DateTime then.
use datetime object you can get the year from it like .year well....
Well, DateTime has the unfortunate side-effect of specifying both a data and a time and not only some subsets. Ideally you would probably want some "time" object with varying levels of accuracy, as needed. But for this I'd suggest using an int since you are modeling exactly a year, not a complete date.
I would create a custom type, (a struct) to hold this value.
public struct FilmYear
{
private int yr;
private bool isDef;
public bool HasValue { return isDef; }
public bool IsNull { return !HasValue; }
private FilmYear(int year) { yr = year; isDef = true; }
public static FilmYear ThisYear = new FilmYear(DateTime.Today.Year);
public static FilmYear LastYear = new FilmYear(DateTime.Today.Year - 1);
public static FilmYear NextYear = new FilmYear(DateTime.Today.Year + 1);
public static FilmYear Parse(DateTime anyDateInYear)
{ return new FilmYear(anyDateInYear.Year); }
public static FilmYear Parse(int year)
{ return new FilmYear(year); }
public static FilmYear Parse(string year)
{ return new FilmYear(Int32.parse(year)); }
public overide string ToString()
{ return yr.ToString(); }
//etc... you can add:
// - operator overloads to add subtract years to the value,
// - conversion operator overloads to implicitly/(or explicitly)
// convert datetimes to FilmYears, as appropriate
// - overload equality and comparison operators ...
}
Usage
FilmYear avatarYear = FilmYear.ThisYear;
FilmYear casablancaYear = FilmYear.Parse(1943);
If this is for casual users, an int (or class based on int) is correct.
If you are doing a 'real' filmography, you'll need both an int and a string: the int for sorting and searching, with the string containing the "truth" of cases where the data is incomplete or tentative ("1958?").
This is also why you shouldn't use a Date or DateTime: there's no way to distinguish between "1/1/1958" and "sometime in 1958".
I think to properly answer that question, you need to supply a little more context. For what kind of application? Is this information going to be stored in a database? What kinds of queries do you expect users to perform against the data? Things like that.
If you're only looking to keep track of the Year, then keep it a int. If you're tracking the release date/production date, then use DateTime
For simplicity using an int is the most direct option; if there are any special methods for the data then creating a Year type and encapsulating all behaviors would be a clean and simple solution--if you go that route you can store the value as either an int or DateTime and offer .ToInt(), .ToDateTime(), methods and others to handle all use-cases.

Categories