How to access variables inside an object? - c#

I am creating an algorithm to fill up a train with animals based on their size and type.
Imagine an animal object in an animal class with a type and size.
/* 0 = Carnivore, Carnivores will eat other animals which are smaller or the same size.
* 1 = Herbivore
* Animal sizes 1, 3, 5 are currently available.
* A trainwagon can fit a maximum of 10 points. The wagon needs to filled optimally.
* A new wagon is added if there are still animals which need to board the train.
*/
public Animal(int type, int size)
{
this.type = type;
this.size = size;
}
I need the value of an animal to sort them. So, I created an override ToString() method to get the value.
public override string ToString()
{
string animalInformation = type.ToString() + size.ToString();
return animalInformation.ToString();
}
I currently solved it by separating the characters of the string and converting them back to integers.
int animalType = Convert.ToString(animalInformation[0]);
int animalSize = Convert.ToString(animalInformation[1]);
My question is: Is there another technique to access the variables in the animal object, because the double conversion impacts the performance of my algorithm in a unneccesary way.

Take another look at your constructor:
public Animal(int type, int size)
{
this.type = type;
this.size = size;
}
This means that type and size are data members of your Animal class, which means that any instance of Animal has a type or a size. this.type is not a variable, but rather a data member of an object, which is similar to a variable due to its changeability, but it's an inherent attribute of an object. If you do something like
Animal animal = new Animal(1, 1);
and then you cannot reach animal.type, that means that animal.type is not public, but rather private or protected. You would be able to reach it if it were public. However, don't change it to public, it's good if you protect your fields from some problematic accesses I'm not describing at this point. Instead, you can define getters, like
public int getType() {
return this.type;
}
public int getSize() {
return this.size;
}
or some readonly properties and get the values by these.

Unless there is some detail not evident from the question, you should just create properties for the fields, i.e.
public readonly struct Animal
{
public int Type { get; }
public int Size { get; }
public Animal(int type, int size)
{
Type = type;
Size = size;
}
}
Sorting can be done with linq. 'ThenBy(...)' is only needed if you need to sort by both properties:
var sortedAnimals = animals.OrderBy(animal => animal.Type).ThenBy(animal => animal.Size);
As mentioned in the comments, if you only want to allow some values for type and size, you should probably use enums. Or at least validate the arguments and throw an exception if the validation fails.

Related

Array of structs inheriting interface appear to be reference types

I have a struct called Foo and Bar - both if these implement an interface called IFoo.
public interface IFoo
{
string StrTest { get; set; }
int NumTest { get; set; }
}
public struct Foo : IFoo
{
public Foo(string backTest, int numTest)
{
StrTest = backTest;
NumTest = numTest;
}
public string StrTest { get; set; }
public int NumTest { get; set; }
}
public struct Bar : IFoo
{
public Bar(string backTest, int numTest)
{
StrTest = backTest;
NumTest = numTest;
}
public string StrTest { get; set; }
public int NumTest { get; set; }
}
Let's say I have an array of IFoo, at index "0" I have a Foo struct. The problem comes when I move that struct over to a new index - such as "1" (which should copy it). Now, you would expect both of them to be separate, meaning you change one and the other shouldn't change as well.
However, I find that if I change one of the properties for the newly moved one - both change... isn't this class (reference type) functionality?
Take a look at the following example:
// Create a list of "BackInterface"s - with foo and bar.
List<IFoo> arr = new List<IFoo>
{
new Foo("A", 2),
new Bar("B", 4)
};
// Now, place the SAME struct at index "0" (the foo) at the end - it should be copied?
arr.Add(arr[0]);
// Modify the item at the last newly-created index
arr[2].StrTest = "C";
Both arr[0] and arr[2]'s StrTest are now "C".
If I have an array of just Foo or Bar I don't have this problem - only when I have an array of IFoo. I have also tried normal arrays (of type "object) and ArrayList (which doesn't have generics) - none of which have worked.
Any idea what is happening in here, and how to still be able to have an array of both Foo and Bar, both having to have an implementation of something?
You can't have an array of both Foo and Bar, both structs, without the boxing you're seeing.
You get boxing if you cast a struct to an interface, which happens when you create List<IFoo> and then put your struct in it. You can see your structs have become reference types by doing
bool test = arr[0].GetType().IsValueType;
after you create arr: it will be false for List<IFoo> and true for List<Foo>.
There are some workarounds, such as having two arrays one for Foo and one for Bar and then another array to index into both of them. But that's horrible. See this earlier Stack Overflow answer for more.
Because of all this in general it's not a great idea to put interfaces on structs: structs are intended to be lightweight things that live on the stack. If you need this behavior you're better off using classes.
By storing the value types in a variable that's of an interface type it gets boxed. Interfaces are always reference types, so implicitly converting a value type implementing it to the interface's type needs to box it. A boxed value type is a reference type, so you're observing reference type behavior because arr[0] is in fact a reference type.

Accessing child class property

I have 2 classes which are inherited in this manner
public class PartsParent
{
}
public class PartsCar : PartsParent
{
public int WheelRadius { get; set; }
public int Price { get; set; }
}
public class PartsBike : PartsParent
{
public int Length { get; set; }
public int Weight { get; set; }
public int Price { get; set; }
}
And i have a function that accepts the class PartsParent as parameter and how can i convert this as partsCar / as PartsBike inside the function and access properties like Price WheelRadius etc?
private int PriceCollection(PartsParent mainObject)
{
int _price=0;
mainObject.OfType(PartsCar).Price;// something similar??
return _price;
}
Well, you are trying to cast a parent type to a child type, that is not really possible, why ?
The answer is that the parent P you are trying to cast to child C1 can be actually and originally of type C2, so the cast would be invalid.
The best way to explain this is a phrase that I read somewhere here on stackoverflow
You can't cast a mammal into a dog - it might be a cat.
You can't cast a food into a sandwich - it might be a cheeseburger.
What you can do though to turn around this situation is something like this :
(mainObject is PartsCar) ? (PartsCar)mainObject : mainObject
Which is equivalent to :
mainObject as PartsCar
Then access mainObject's cast result using the null coalescing operator (because if as fails, the cast result will be null instead of throwing an Exception).
The generic method OfType<T> that you tried to use is an extension method that can be used with objects of type IEnumerable<T'> , which I guess is not your case.
The idea of inheritance is to group up what is common in a super class, and leave other specific details to sub-classes. So if a property, say Price, is excepted from all sub-classes, then it should be declared in the super class.
However, if you still want to use it this way, then what are you looking for is:
int _price = ((PartsCar)mainObject).Price;
However, what if the object was of some other class, say PartsGift that inherits from PartsParent, but does not have a price? Then it will crash.
You almost really need to check your design.
BTW, if you want to check if an object is really of a specific class, then you can use is.
int number = 1;
object numberObject = number;
bool isValid = numberObject is int; // true
isValid = numberObject is string; // false
You can use is keyword to check the type and as keyword to convert to the target child type as following.
if (mainObject is PartsCar)
{
var partscar = mainObject as PartsCar;
// Do logic related to car parts
}
else if (mainObject is PartsBike)
{
var partsbike = mainObject as PartsBike;
// Do logic related to bike parts.
}
It's possible if you separate uncommon properties your code into block:
if (mainObject is PartsCar)
{
//Seprated code for PartsCar
// WheelRadius...
//Price...
}
else if (mainObject.GetType() == typeof(PartsBike))
{
//Seprated code for PartsBike
//Length
//Weight
//Price
}

How to access value out of dictionary whose key is complex type?

In writing an insurance premium calculator the basic scheme is as follows: Points are assigned to a predetermined number of attributes, such as car-value, num-incidents-in-past, years-experience-driving etc. Hene, if car worth is $3800, that lies within the 3001 to 4000 range which warrants 30 points in the premium calculation. If num-incidents-in-past is 3 or below, that warrants ZERO points. If 4-5 num-inc then points warranted is 5. If years-exp is between 1-5, that warrants 12 points. The idea is an arbitrary value is being assigned to a range of values for any given number of attributes. The premium calculations is simply tallying up the points warranted for each attribute category and multiplying by some factor i.e 2.5. I am trying to use B. LISKOV'S power of abstractions AND the SRP to neatly assign responsiblities to design a calculator that is extensible and well designed.
Based on the answer provided by drharris here Is there a C# type for representing an integer Range?
How do I access the value out of the following Dictionary whose key is a generic type Range as defined by drharris?
//************************ABSTRACTIONS************************
public abstract class AbsPerson
{
public virtual AbsPolicy APolicy { get; set; }
public virtual string ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public virtual string Address { get; set; }
}
public abstract class AbsPolicy
{
public virtual string PersonID { get; set; } //FK
public virtual int PropValue { get; set; }
public virtual int InsGroup { get; set; }
}
public abstract class AbsValueCategoryCalculator: IEvaluatePolicy
{
//DATA
public abstract void InitRange();
//REFERENCE drharris poster GENERIC TYPE SIGNATURE - public class Range<T> where T : IComparable<T>
public abstract Dictionary<Range<int>, int> ValueRange {get; set;}
public abstract int Tally { get; set; }
//BEHAVIOUR
public virtual void EvaluatePolicyDetails(AbsPerson person)
{
}
}
public interface IEvaluatePolicy
{
void EvaluatePolicyDetails(AbsPerson person);
}
//*************************CONCRETIONS**************************
public class CarValueCategoryCalculator : AbsValueCategoryCalculator
{
public CarValueCategoryCalculator()
{//ctor
InitRange();
}
public override void InitRange()
{
this.ValueRange = new Dictionary<Range<int>, int>();
this.ValueRange.Add(new Range<int>() { Minimum = 1000, Maximum = 2000 }, 10);
this.ValueRange.Add(new Range<int>() { Minimum = 2001, Maximum = 3000 }, 20);
this.ValueRange.Add(new Range<int>() { Minimum = 3001, Maximum = 4000 }, 30);
this.ValueRange.Add(new Range<int>() { Minimum = 4001, Maximum = 5000 }, 40);
this.ValueRange.Add(new Range<int>() { Minimum = 5001, Maximum = 6000 }, 50);
this.ValueRange.Add(new Range<int>() { Minimum = 6001, Maximum = 7000 }, 60);
}
public override Dictionary<Range<int>, int> ValueRange
{
get; set;
}
public override void EvaluatePolicyDetails(AbsPerson person)
{
//I am trying to tally the value given wether the cars worth lies within the range
if (this.ValueRange.ContainsKey(new Range<int>() { Maximum = person.APolicy.PropValue, Minimum = person.APolicy.PropValue }))
{
this.Tally =
}
Console.WriteLine("good");
}
public override int Tally
{
get;set;
}
}//end class
(As noted in comments, Sam's answer points out that a dictionary isn't really what's wanted here - that only finds equal keys, whereas the OP is trying to find a range key that contains a single value. Hash tables just aren't geared up for that.)
You need to either override GetHashCode and Equals in Range<T> (which would be sensible - ideally implementing IEquatable<Range<T>> at the same time) or create a separate type which implements IEqualityComparer<Range<T>> and then pass that to the dictionary constructor.
I would probably do it on the range type, like this:
public sealed class Range<T> : IEquatable<Range<T>>
where T : IComparable<T>, IEquatable<T>
{
...
public override int GetHashCode()
{
int hash = 23;
hash = hash * 31 + EqualityComparer.Default<T>.GetHashCode(Minimum);
hash = hash * 31 + EqualityComparer.Default<T>.GetHashCode(Maximum);
return hash;
}
public override bool Equals(object other)
{
return Equals(other as Range<T>);
}
public bool Equals(Range<T> other)
{
if (ReferenceEquals(other, this))
{
return true;
}
if (ReferenceEquals(other, null))
{
return false;
}
return EqualityComparer<T>.Default.Equals(Minimum, other.Minimum) &&
EqualityComparer<T>.Default.Equals(Maximum, other.Maximum);
}
}
Note that currently the Range<T> type is mutable, however - that's generally a bad idea for dictionary keys. It would be a good idea to make it at least "shallow-immutable" - there's not a lot you can do if the
You'll either need to override Equals and GetHashCode on Range such that the items are compared based on the values you're interested in (min and max) rather than the default behavior (which is based on the object's reference).
If you cannot mutate the type (or don't want to) then you can create a type that implements IEqualityComparer<Range<T>>, implements the appropriate equals and hash generation methods, and then create an instance of that comparer that you pass to the dictionary.
I'm trying to read between the lines here, and I think that you are asking the wrong question.
This bit of code catches my eye (you may want to make it clearer so that others understand your need better):
public override void EvaluatePolicyDetails(AbsPerson person)
{
//I am trying to tally the value given wether the cars worth lies within the range
if (this.ValueRange.ContainsKey(new Range<int>() { Maximum = person.APolicy.PropValue, Minimum = person.APolicy.PropValue }))
{
this.Tally =
}
Console.WriteLine("good");
}
I think that what you are actually trying to do here is fetch the associated int value when person.APolicy.PropValue is within a Range.
What you are currently doing is wrong, and will not work, even if you add the proper Equals and GetHashCode overrides. Dictionaries only do exact matches. You are trying to do range matching.
Instead, I suggest you drop the dictionary in favor of a List of a new type composed of a Range and whatever that int value is. Then I would sort the list based on the Range's Minimum value. Then, you could optionally do a binary search in the list to quickly find candidate Range objects, and then use the Range.ContainsValue function to verify if person.APolicy.PropValue is within the range. Or, in this case, given that you only have a handful of Ranges, you can just iterate over the whole list and break out of the loop as soon as you find a Range that contains your value.
This is definitely a bit more work for you, but I think that this will get you what you are really looking for.

Know when variables inside a struct become null in Visual Studio?

I have a struct on the server-side with a layout like this:
struct SomeStruct
{
public string SomeString { get; set; };
public string SomeString1;
public string SomeString2;
public string SomeString3;
}
I am using a client/server model, and an instance of this struct gets referenced a lot of times as it has really important information (over 200 times).
The thing is that when some function gets called, the values inside this struct become null. I don't know why and it is been bugging me for a really long time.
I call a lot of methods before realizing that this values are null, so I don't know which section of my code nullify my strings.
I am using VS2012, but I have 2010 and 2008 ultimate as well. I was wondering if there is a way to perform a trigger when some section of code nullifies my strings.
I tried to add some properties like this, bot the exception was never thrown:
struct SomeStruct {
string somestr;
public string SomeString
{
get { return somestr; }
set
{
if (value == null)
{
throw new Exception("stirng is null");
}
somestr = value;
}
}
public string SomeString1;
public string SomeString2;
public string SomeString3;
}
Might not be important, but this is one of the structs I am using (the Name variable becomes null in some part of my code, and the rest turns into default()):
[ProtoContract]
public struct CharacterInformation
{
[ProtoMember(2)]
public string Name;
[ProtoMember(3)]
public IntegerVector2 Position;
[ProtoMember(5)]
public CharacterDirection Direction;
[ProtoMember(6)]
public CharacterStatus Status;
[ProtoMember(7)]
public CharacterClass Class;
[ProtoMember(8)]
public CharacterRace Race;
[ProtoMember(9)]
public CharacterType Type;
[ProtoMember(10)]
public CharacterFaction Faction;
[ProtoMember(11)]
public float MovementModifier;
[ProtoMember(12)]
public CharacterEquipment Equipment;
}
Edit: The only instance of this struct is created on a Sql-related function:
public CharacterServerInformation GetInformation(int charID)
{
CharacterServerInformation information = new CharacterServerInformation();
if (!authInstance.CharacterExists(charID))
{
// char doesn't exists
throw new Exception("Character doesn't exists");
}
information.ID = charID;
information.Experience = GetExperience(charID);
information.Info.Direction = CharacterDirection.Bottom;
information.Info.Name = authInstance.CharacterGetName(charID);
information.Info.Class = GetClass(charID);
information.Info.Faction = GetFaction(charID);
information.Info.Position = GetPosition(charID);
information.Info.Race = GetRace(charID);
information.Info.Status = GetStatus(charID);
information.Info.Type = GetType(charID);
information.Info.MovementModifier = 1f; // should store old movement modifier, but well, whatever
information.HealthLeft = GetHealthLastLogout(charID);
return information;
}
I suspect the problem is purely because you're using struct and not making a class. Since struct members are copied by value into methods and when returned from methods, including property getters, it's likely that you're "losing" the information by accidentally writing a new struct somewhere.
In this case, class seems is far more appropriate. If you read Choosing Between Classes and Structures, you'll see that struct should only be used when:
It logically represents a single value, similar to primitive types (integer, double, and so on).
It has an instance size smaller than 16 bytes.
It is immutable.
It will not have to be boxed frequently.
In your case, all of these criteria ( except maybe the last) are being violated, so class would be more appropriate.

Referring to attributes in generic types?

I'm teaching myself C#, so forgive me if this seems slightly obvious.
I'm trying to write a generic function that I can pass an array of structs into and then use one of the attributes of the struct. I have no idea how to declare a generic datatype in a function in a way that I can refer to attributes in the way needed.
Maybe what I'm asking can be better communicated in code - this is a non-working function to illustrate what I'm trying to do, how it strikes me as logical that it should work without actually knowing how to write it:
public static int AFunctionIsThis<DataType, int DataType.Value>(DataType passedrecord)
{
temp = passedrecord.Value * 2 + 1;
return temp;
}
And I want to be able to call it normally while specifying the attribute of the struct to be passed.
int NewVariable = AFunctionIsThis<ThisIsAStruct, ThisIsAStruct.AnIntAttribute>(ThisIsADeclaredStruct);
Thankyou very much,
Hanii Puppy.
You can't specify members that a generic type should contain, you can only specify the generic data type.
You would use an interface where the property is defined:
public interface IHaveValue {
int Value { get; }
}
Your struct would then implement the interface, and you can specify the interface as the generic data type:
public static int AFunctionIsThis<T>(T passedrecord) where T : IHaveValue {
return passedrecord.Value * 2 + 1;
}
However, with what you are using it for, you don't need to use generics at all, you can just use the interface:
public static int AFunctionIsThis(IHaveValue passedrecord) {
return passedrecord.Value * 2 + 1;
}
Note that you should most likely not use a struct at all, but a class. A struct is more complicated to implement correctly, so you should stick to classes until you have a really good reason to use a struct.
(To start with, note that the word "attribute" has a different meaning in .NET from the OOP sense.)
Use a Converter<T,int> and Action<T,int> delegate to get and set the member, respectively.
e.g.
public static int AFunctionIsThis<DataType>(DataType passedrecord, Converter<DataType,int> getter)
{
temp = getter(passedrecord) * 2 + 1;
return temp;
}
and then call it
AFunctionIsThis(ThisIsADeclaredStruct, x => x.AnIntProperty);
If you also need to set the value, you can use
AFunctionIsThis(ThisIsADeclaredStruct, x => x.AnIntProperty, (x, v) => { x.AnIntProperty = v; });
or do some magic with Expression<Converter<T>> to yank out the member reference and create a matching setter.
Hanii Puppy:
In short, yes, you should be able to do what you are doing, but here is a syntax that works:
public static int AFunctionIsThis<T>(T passedRecord) where T : DataType
{
var temp = passedRecord.Value;
return temp;
}
public class DataType
{
public int Value { get; set; }
}
Hope that helps.
Dave
What you want to do, is define a generic method that accepts only T that implements a certain interface or is derived from certain base class that has an int member called Value.
e.g:
public interface IClass { int Value{get;set;} }
public class ExampleImpl : IClass
{
int Value{get;set;}
/* Additional Members\methods here */
}
public class HelperClass
{
public static int GenMethod<T>(T item) where T:IClass
{
return item.Value * 2 + 1;
}
}

Categories