Default value in string property [duplicate] - c#

I'm trying to make default value for my struct.
For example default value for Int - 0, for DateTime - 1/1/0001 12:00:00 AM.
As known we can't define parameterless constructor in structure.
struct Test
{
int num;
string str;
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(default(Test)); // shows namespace and name of struct test.Test
Console.WriteLine(new Test()); // same
Console.ReadKey(true);
}
}
How can I make a default value for struct?

You can't. Structures are always pre-zeroed, and there is no guarantee the constructor is ever called (e.g. new MyStruct[10]). If you need default values other than zero, you need to use a class. That's why you can't change the default constructor in the first place (until C# 6) - it never executes.
The closest you can get is by using Nullable fields, and interpreting them to have some default value if they are null through a property:
public struct MyStruct
{
int? myInt;
public int MyInt { get { return myInt ?? 42; } set { myInt = value; } }
}
myInt is still pre-zeroed, but you interpret the "zero" as your own default value (in this case, 42). Of course, this may be entirely unnecessary overhead :)
As for the Console.WriteLine, it simply calls the virtual ToString. You can change it to return it whatever you want.

Your problem is not with the behaviour of C#/.Net. The way you instantiate the struct effectively creates an instance with default values for all member fields.
The Console.WriteLine converts its argument to a string using the ToString() method. The default implementation (Object.ToString()) simply writes the fully qualified class name (namespace and name, as you call it).
If you want another visualisation, you should override the ToString method:
public struct Test
{
int num;
string str;
public override string ToString()
{
return $"num: {num} - str: {str}";
}
}

This is my take on this in case somebody finds it useful.
public struct MyStruct
{
public int item1;
public float item2;
public float item3;
public static MyStruct Null => new MyStruct(-1, 0, 0);
}
I have a static method inside my struct so that I can do this:
var data = MyStruct.Null;
instead of
var data = new MyStruct();
data.item1 = -1;
...
Or create a custom constructor to pass the data.

Printing out objects of the C# results with namespaces unless you override .ToString() for your objects. Can you define your struct like below and try it ?
public struct Test
{
int num;
string str;
public override string ToString()
{
return "Some string representation of this struct";
}
}
PS: default(Test) gives you a struct contains default(int) and default(string) which I mean Test.num is 0 and Test.str is null
Hope this helps

You can also do this:
public struct MyStruct
{
public static readonly Default = new MyStruct(42);
public int i;
public MyStruct(int i)
{
this.i = i;
}
}
And then when you create a default struct of this type do this:
public MyStruct newStruct = MyStruct.Default;
But of course, this won't override default and other programmers will bump their heads a few times. Really consider if a struct is the way to go, from the microsoft docs:
"A structure type (or struct type) is a value type that can encapsulate data and related functionality. Typically, you use structure types to design small data-centric types that provide little or no behavior."
Consider this: if you had 2 values in your struct and you wanted to make constructors, would 2 or less constructors suffice? If the answer is no, then the answer is: don't use a struct.

What you probably want to do is to override ToString(), e.g.
struct Test
{
int num;
string str;
public override string ToString ()
{
return string.Format ($"{str} | {num}");
}
}
As you have mentioned, it is impossible to define default values for fields other than default values for their appropriate types. However, with an overriden ToString(), you will see better formatted information about your structure in the console and during debugging.

Related

Can someone explain this C# syntax?

What's actually going on here:
public decimal[] Coefficients;
public decimal this[int i]
{
get { return Coefficients[i]; }
set { Coefficients[i] = value; }
}
What does the this serve as? Is it some sort of extension to the decimal?
It's an Indexer.
Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.
Example from the linked MSDN:
class SampleCollection<T>
{
// Declare an array to store the data elements.
private T[] arr = new T[100];
// Define the indexer, which will allow client code
// to use [] notation on the class instance itself.
// (See line 2 of code in Main below.)
public T this[int i]
{
get
{
// This indexer is very simple, and just returns or sets
// the corresponding element from the internal array.
return arr[i];
}
set
{
arr[i] = value;
}
}
}
// This class shows how client code uses the indexer.
class Program
{
static void Main(string[] args)
{
// Declare an instance of the SampleCollection type.
SampleCollection<string> stringCollection = new SampleCollection<string>();
// Use [] notation on the type.
stringCollection[0] = "Hello, World";
System.Console.WriteLine(stringCollection[0]);
}
}
// Output:
// Hello, World.
It is an indexer it will be called when you use syntax like obj[1]. https://msdn.microsoft.com/en-us/library/6x16t2tx.aspx
Have you ever wondered how List<T>'s myList[i] works in c# just like an array ?
The Answer is in your question. The syntax you posted is a syntactic sugar that the compiler transforms into properties called get_Item(int index) and set_Item(int index, decimal value). It is used in List<T> for example to access the internal array used in the class and return the element at the specified index (set or get). This feature is called an Indexer.
To test that yourself, try to create a method with same signature :
public decimal get_Item(int i)
{
return 0;
}
You'll get a compiler error :
Error CS0082: Type 'MyClass' already reserves a member called
'get_Item' with the same parameter types

Is it possible to change default value for value types variables? [duplicate]

This question already has answers here:
Is it possible to change the default value of a primitive data type?
(6 answers)
Closed 7 years ago.
I'm just curious to know, is it possible to change default value of e.g. int in C# and I can have a value -1 instead of 0.
public class Foo {
public int i;
}
...
foo = new Foo();
Console.Write(foo.i);
so this code must return
-1
Without explicit initializing
public class Foo {
public int i = -1;
}
Can I always be sure, that someone don't print somewhere something like
#define TRUE FALSE
but for default value of int
P.S. for interest purposes only.
No, basically. Assuming you don't initialize fields, the memory space is simply zeroed. You shouldn't expose fields directly anyway.
One trick I have seen to get around this (used by the capnp serializer, which works against raw memory, not objects) is to use xor. For example: if the default is -1, you can xor the value in and out:
public class Foo {
private int i;
public int I {
get { return i ^ -1; }
set { i = value ^ -1; }
}
}
This has no initialization, and does what you want. For use with types other than bools and integers this is more complex, but still possible - but it would be easier to use an initializer.
Note that for the -1 case, you could use "not" rather than "xor":
public class Foo {
private int i;
public int I {
get { return ~i; }
set { i = ~value; }
}
}
However: a field initializer (int i = -1;) or a constructor (public Foo() { i = -1; }) is probably simpler.
You can't change int's default value, but you can set Foo's variables default value:
public class Foo
{
public int i;
public Foo()
{
i = -1;
}
}
As far as I know, you can not change the default value of value types.
But you can certainly initialize it to a value you want.
for eg.
public class Foo {
public int i = -1;
}
...
foo = new Foo();
Console.Write(foo.i);
it will return
-1
A nice solution would be to override default(T), but you can't override this keyword. It is always null for reference types and zero for value types.

how can i do binary search on an array of structs w.r.t a particular field value in c#?

I have an array of structs, where the struct has three integer fields. It is sorted by one of the fields, say F, and I want a way to do a binary search with respect to this field, that is, a function of the form binarySearch(mystruct[] myarray, int val) which returns the index of the structure in which field F = val. I know that there is an existing Array.BinarySearch(T[] array, T value) function, but it only allows to search for a type T that is the same as the types in the array. This means that if I want to search with respect to a value, I need to create a new struct and set field F to that value just so that I can pass it to this function. I don't think there would be significant performance overhead but it seems ugly. The other way I can think is to implement the function myself, but this also seems inelegant when something so similar exists. Any suggestions for a better way or which way would be preferred?
You can either implement IComparable<T> for your struct to compare on the field (F), or you can create an IComparer<> for your struct that will compare based on that field and pass that into Array.BinarySearch().
So either:
// using IComparable<T>
public struct MyStruct : IComparable<MyStruct>
{
public int F { get; set; }
// other fields that should not affect "search"
public int X { get; set; }
public int CompareTo(MyStruct other)
{
return F.CompareTo(other.F);
}
}
Which can be called as:
MyStruct target = new MyStruct { F = 13 };
Array.BinarySearch(arrayOfMyStruct, target);
Or a separate IComparer<MyStruct>:
public struct MyStruct
{
public int F { get; set; }
// other non-sort/search affecting properties
public int X { get; set; }
}
public struct MyStructComparer : IComparer<MyStruct>
{
public int Compare(MyStruct x, MyStruct y)
{
return x.F.CompareTo(y.F);
}
}
Which can be called like:
MyStruct target { F = 13; }
Array.BinarySearch(myArrayOfStruct, target, new MyStructComparer());
The first has less code, but it strongly couples ordering to the type, which if you want to alter ordering based on situation (that is, allow multiple sort orders), this isn't ideal. The latter gives more flexibility in that you can provide multiple different orders independent of the struct, but it does require an extra class.
UPDATE
If you don't want to create a dummy struct to compare against, you can implement IComparable like:
public struct MyStruct : IComparable
{
public int F { get; set; }
// other non-sort/search affecting properties
public int X { get; set; }
public int CompareTo(object other)
{
// if the type is NOT an int, you can decide whether you'd prefer
// to throw, but the concept of comparing the struct to something
// unknown shouldn't return a value, should probably throw.
return F.CompareTo((int)other);
}
}
Which could be called like:
Array.BinarySearch(arrayOfMyStruct, 13);
But again, this strongly ties your implementation of the class to a given comparison type, which I think is uglier than using a dummy search target, but that's my personal preference. Personally, especially with initializer syntax being as short as it is, I prefer to use the dummy target:
var target = new MyStruct { F = 13 };
UPDATE: You can support both int and MyStruct comparissons, but it gets messy quickly, which is why I personally, again, recommend using the dummy struct to avoid the headaches:
// implement IComparable<int> for the int search (w/o dummy), and IComparable<MyStruct> for sort
public struct MyStruct : IComparable, IComparable<MyStruct>, IComparable<int>
{
public int F { get; set; }
// other non-sort/search affecting properties
public int X { get; set; }
public int CompareTo(object other)
{
if (other is int)
return F.CompareTo((int)other);
if (other is MyStruct)
return F.CompareTo((MyStruct)other);
throw new InvalidOperationException("Other must be int or MyStruct.");
}
public int CompareTo(MyStruct other)
{
return F.CompareTo(other.F);
}
public int CompareTo(int other)
{
return F.CompareTo(other);
}
}
If your struct implements IComparable, you can use:
// myValue is an the value of the field to compare to
Array.BinarySearch(myArray, myValue);
as described in http://msdn.microsoft.com/en-us/library/y15ef976.aspx
You can compare a struct to an object with IComparable, so you can pass in the value intead of a new struct. In your implementation of CompareTo, you can compare any value with the field value, allowing you to say 'My struct should be considered greater/less than this number'.
EDIT:
Here is an example of CompareTo for your struct:
public int CompareTo(object obj)
{
if (obj is int)
{
return myIntField.CompareTo((int)obj);
}
return 0;
}
One way would be to create a custom IComparer<T> that compares instances of your struct based only on the value of that field and pass it to this overload of BinarySearch (you will also need to create a "dummy" struct instance to compare to). This is probably the purest solution.
However, as a practical matter you can use LINQ to project into a collection of field values and binary search into that; the resulting index will be the same as if you had searched the struct collection itself. For example:
var structs = new MyStruct[n];
var index = structs.Select(i => i.F).ToList().BinarySearch(42);
In the code above, F is the vame of the field and 42 is the value you are searching for (its type would be the type of F). This is not going to be as fast, but you don't need to write any code and speed could very well be irrelevant in your case.
Update: To clarify: obviously, the code above will be O(n) due to the projection operation so using binary search once after projecting like that is silly (you can simply do a linear search instead). However, if you intend to make multiple searches then it might start making sense.
I would definitely not recommend overriding Equals in your struct unless comparisons between instances are meant to be reduced to comparing F members everywhere in your application.

Why I cannot derive from long?

My function returns some long value
which contains two values in lower and higher 32 bits.
I thought the best ways to handle return value
is to derive my custom type from long and provide
type extenders like GetLowerValue(), GetHigherValue().
The problem is that .NET does not allow to derive from long
If you compile that
public class SubmitOrderResult : long
{
}
you get:
cannot derive from sealed type 'long'
Why is that designed so and how can overcome it?
Thanks
As already mentioned value types in .NET are sealed so there is no way you can derive from long. You should create extension methods as suggested.
Example
public static class LongExtensions
{
public static long GetLowerValue(this long value)
{
...
}
public static long GetHigherValue(this long value)
{
...
}
}
You can't derive from any of the .NET Value Types - they are all sealed by definition.
Perhaps you could implement your GetLowerValue and GetHigherValue methods as extension methods?
My function returns some long value which contains two values in lower and higher 32 bits.
That sounds like a really, really dirty hack. It could be appropriate for close-to-metal languages (e.g. C) but not for a higher-level, object-oriented language.
In OO languages, you extend the type system, not harass existing types to do your bidding. Thus, the solution should be to create a new type which carries your information.
What you can do is write a struct with implicit conversion operators. That will work exactly the way you want:
public struct SubmitOrderResult
{
private long _result;
public SubmitOrderResult(long result)
{
_result = result;
}
public long Result
{
get { return _result; }
set { _result = value; }
}
public int GetHigherValue()
{
return (int)(_result >> 32);
}
public int GetLowerValue()
{
return (int)_result;
}
public static implicit operator SubmitOrderResult(long result)
{
return new SubmitOrderResult(result);
}
public static implicit operator long(SubmitOrderResult result)
{
return result._result;
}
}
Then you can do:
SubmitOrderResult result = someObject.TheMethod();
Console.WriteLine(result.GetHigherValue());
Console.WriteLine(result.GetLowerValue());
...just like you wanted.
If I understand correctly, your function actually returns two values, and the fact that you pack them into a long is an implementation detail. In that case, hide this detail and create a class which contains the value and the required operations:
public class SubmitOrderResult
{
private readonly long value_;
public int OneValue
{
get { return (int)(value_ >> 32); }
}
public int TheOtherValue
{
get { return (int)(value_ & 0xFFFFFFFF); }
}
public SubmitOrderResult(long value)
{ value_ = value; }
}
You can't overcome it.
As long is a sealed type and therefore you can't inherit from them. See the MSDN
Because structs are implicitly sealed, they cannot be inherited.
For more information, see Inheritance (C# Programming Guide).

Best way to design a multi-type object

Let's say I have a data object, but this object can hold one of several types of data.
class Foo
{
int intFoo;
double doubleFoo;
string stringFoo;
}
Now, I want to create an accessor. Some way to get at this data. Obviously, I could create multiple accessors:
public int GetIntFoo();
public double GetDoubleFoo();
public string GetStringFoo();
Or I could create multiple properties
public int IntFoo { get; set; }
public double DoubleFoo { get; set; }
public string StringFoo { get; set; }
I don't that this is a very good design. It requires the client code to be more concerned about type than it should have to be. What's more, I really need only a single value for this class and the above would allow one of each type to be assigned at the same time. Not good.
One option is to use Generics.
class Foo<T>
{
public T TheFoo { get; set; }
}
However, this doesn't create a Foo, it creates a Foo<T>. A different type for each, so I can't really use them as the same type.
I could derive Foo<T> from FooBase, then treat all of them as FooBase's, but then i'm back in the problem of accessing the data.
A different Generics option is to use something like this:
class Foo
{
string stringRepresentationOfFoo;
public T GetFoo<T>() { return /* code to convert string to type */ }
}
OF course the problem is that any kind of T could be passed, and frankly, it's a bit busy.
I could also just box the values and return an object, but then there is no type safety.
Ideally, I want to treat all Foo's the same, but I want type safety so that if there isn't a StringFoo, I can't even compile a reference to a StringFoo.
Foo foo = new Foo("Foo");
string sFoo = foo.Value; // succeeds.
Foo foo = new Foo(0);
int iFoo = foo.Value; // succeeds
string sFoo = foo.Value; // compile error
Perhaps this isn't even possible.. and I'll have to make some compromises, but maybe i'm missing something.
Any ideas?
EDIT:
Ok, so as daniel points out, the compile time checking of a runtime type is not practical.
What is my best option for doing what I want to do here? Namely, Treat all Foo's the same, but still have a relatively sane access mechanism?
EDIT2:
I don't want to convert the value to different types. I want to return the correct type for the value. That is, if it's a double, I don't want to return an int.
How about passing in the variable as a parameter to the get? Like this:
int i = foo.get(i);
Then in your class, you'd have something like:
public int get(int p) {
if(this.type != INTEGER) throw new RuntimeException("Data type mismatch");
return this.intVal;
}
public float get(float p) {
if(this.type != FLOAT) throw new RuntimeException("Data type mismatch");
return this.floatVal;
}
This sort of turns the type checking inside-out: instead of checking what type foo holds, you have foo check what type you want. If it can give you that type, it does, or else it throws a runtime exception.
I don't think this could work (giving you the compiler error you want)
What would you want this to do:
Foo bar = (new Random()).Next(2) == 0 ? new Foo("bar") : new Foo(1);
int baz = bar.Value;
Is that a compiler error?
I think "treat them all the same" (at least the way you've described it) and "compile time error" are going to be mutually exclusive.
In any case, I think the "best way" is going to be a compromise between generics and inheritance. You can define a Foo<T> that is a subclass of Foo; then you can still have collections of Foo.
abstract public class Foo
{
// Common implementation
abstract public object ObjectValue { get; }
}
public class Foo<T> : Foo
{
public Foo(T initialValue)
{
Value = initialValue;
}
public T Value { get; set; }
public object ObjectValue
{
get { return Value; }
}
}
Many systems use a helper methods to return the alternate types just as the .net frameworks base object has the ToString() method
Choose which is the best base type for each of your object and provide To methods for other cases
e.g.
class Foo{
public Int32 Value { get; set; }
public Byte ToByte() { return Convert.ToByte(Value); }
public Double ToDouble() { return (Double)Value; }
public new String ToString() { return Value.ToString("#,###"); }
}
One thing is to store any type in your internal state of the class, and another is to expose it externally. When you write a class, you are actually declaring a contract for its behavior. The way you write it will influence greatly how client code will look like when using the class.
For example, by implementing the IConvertible interface you state that your type can be converted to any CLR type as an equivalent value.
I have also seen implementations where a Value class was used to store results of calculations, results that could represent either a string, double, int or boolean. But, the problem was that client code had to check a Value.Type property of an enum {String, Integer, Double, Boolean} and then either cast the Value.Value property (which was exposed externally by the Value class as an Object type) or use the specific ValueString, ValueDouble, ValueInt, ValueBoolean getters.
Why not just use string, double and int?
After info about collection: What about using object? You will have to check for types and such afterwards anyways. And to help you with that you can use the is and as operators. And the Enumerable.Cast Method, or even better, the Enumerable.OfType Method.
Actually, what is the purpose of this class? The biggest problem seems to be design breaking at least SRP (single responsibility principle).
Nonetheless, if I'm reading it correctly, you'd like to store some value in the container, pass the container to client and type-safely retrieve the value.
With this approach, you can use your proposal, i.e.
namespace Project1 {
public class Class1 {
static int Main(string[] args) {
Foo a = new Foo();
a.SetValue(4);
Console.WriteLine(a.GetValue<int>());
Foo b = new Foo();
a.SetValue("String");
Console.WriteLine(a.GetValue<string>());
Console.ReadLine();
return 0;
}
}
class Foo {
private object value; // watch out for boxing here!
public void SetValue(object value) {
this.value = value;
}
public T GetValue<T>() {
object val = this.value;
if (val == null) { return default(T); } // or throw if you prefer
try {
return (T)val;
}
catch (Exception) {
return default(T);
// cast failed, return default(T) or throw
}
}
}
}
However, in that case why not simply pass data as object and cast by yourself?
Depending on your needs, you may also try "PHP in C#":
namespace Project1 {
public class Class1 {
static int Main(string[] args) {
MyInt a = 1;
MyInt b = "2";
Console.WriteLine(a + b); // writes 3
Console.ReadLine();
return 0;
}
}
class MyInt {
private int value;
public static implicit operator int(MyInt container) {
return container.value;
}
public static implicit operator MyInt(int value) {
MyInt myInt = new MyInt();
myInt.value = value;
return myInt ;
}
public static implicit operator MyInt(string stringedInt) {
MyInt myInt = new MyInt();
myInt.value = int.Parse(stringedInt);
return myInt;
}
}
}
I'm sorry, I just don't buy your premise. If the data all have the same purpose, then they should all have the same type. Consider a class that's meant to hold the current temperature, as returned by one of several web services. All the services return the temperature in Centigrade. But one returns as an int, one returns as a double, and one returns it as a string.
It's not three different types - it's one type - double. You would simply need to convert the non-double returns into double, which is what the temperature is (or maybe float).
In general, if you have multiple representations of one thing, then it's still one thing, not multiple things. Convert the multiple representations into one.

Categories

Resources