Referring to attributes in generic types? - c#

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

Related

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
}

Forcing all class fields be initialized

Similar to struct in c#, that all fields in it must be initialized at compiling time, I'm interested to know if there is some way to obligate a programmer to initialize all the fields in a class and to have indication (error) while compiling a code.
Have a good day,
Thanks.
Providing a constructor that takes all properties as parameter, as NDJ said, is a good idea.
If you really want to get a warning or an error on compilation in case you forgot to update your constructor after adding a new property, you could build a custom Code Analysis rule (using the FxCop SDK) and check that every setter of public properties is called in the class constructor.
the easiest way is to provide a constructor which takes the fields you want to initialise - e.g.
public class MyClass
{
public string MyValue { get; set; }
public MyClass(string myValue)
{
MyValue = myValue;
}
}
I really can't see the point of this, but:
You've already pointed out that a struct enforces this. Therefore you can do something like what you want by putting all the class's fields in a struct. Then if you add a new field to the struct, it will force you to add the field initialisation to the struct's constructor.
class Test
{
public Test(int x, string y)
{
fields = new Fields(x, y);
}
public int X
{
get
{
return fields.X;
}
set
{
fields.X = value;
}
}
public string Y
{
get
{
return fields.Y;
}
set
{
fields.Y = value;
}
}
struct Fields
{
public Fields(int x, string y)
{
X = x;
Y = y;
}
public int X;
public string Y;
// Uncomment this and you get an error:
// public double Z;
}
Fields fields;
}
This isn't really all that you want though - because you could still just add a field outside the struct. So I guess it doesn't really help a lot...

Read property from the same class

In C# if I have this in a class:
public int SomeNumber
{
get { return 6; }
}
How can I read (get) that number from a function in the same class if the function receives a variable with the same name? Example:
public bool SomeFunction(int SomeNumber)
{
check if SomeNumber (the one passed to this function) == SomeNumber (the one from the public int)
}
You would simply invoke the property get in the method:
public void MyMethod()
{
var someNum = SomeNumber; // basically, var somNum = this.SomeNumber;
}
EDIT: To clarify with OP's edit:
public void MyMethod(int someNumber)
// Change the naming of your parameter so it doesnt clash with the property
{
if(someNumber == SomeNumber)
// Do Stuff
}
Same as if it were a field:
public void SomeOtherFunction()
{
var x = SomeNumber;
}
Although the other suggestions do work well (and adhere to easier to read/maintain code), they don't directly answer your question. Given a class
public class SomeClass
{
public int SomeNumber { get { return 6; } }
...
And a function with a parameter passed in
public void SomeMethod(int SomeNumber)
{
// Your code here...
You can access the passed in parameter and property like so:
if (SomeNumber > this.SomeNumber)
{
// Your results here
The distinction is that if you refer to just the variable name, it will use the variable from the same scope, i.e. the passed in variable. If you specify use "this." then you always get the class member.
Note: This does not work with Static classes, as there is no instance of the class. (Can't use "this.whatever") and you will be stuck. There are many coding Standards out there and some of them states that it is best practice to use the form "myVariable" for method parameters, "MyVariable" for property names, and _myVariable for property backing stores, to easily distinguish between them in your code.
public class FavoriteNumber
{
public int SomeNumber
{
get { return 6; }
}
Public int Twelve()
{
return SomeNumber*2;
}
}
Please run this code and you will get it.. Use this operator to refer the class level variale.
public void CheckNumber(int SomeNumber)
{
Console.WriteLine(SomeNumber);
Console.WriteLine(this.SomeNumber);
}

Required property in a template type in C#

Considering a generic method, is there a possibility to set a constraint on the template type to have some specific properties?
In order to compile successfully the following code for example
public static int[] DoSomething<T> (T[] Input)
{
int[] Output = new int[Input.Length];
for (int i = 0;i < Input.Length;i++)
Output[i] = (int)Input[i].PropertyA+(int)Input[i].PropertyB;
return Output;
}
the template type needs to implement the PropertyA and PropertyB.
Is it possible somehow to set such a constraint on the template type?
EDIT:
And require in addition that PropertyA and PropertyB to be numeric types so they could be typed to int.
Thanks.
The only possibility is to define T as type derived from some well known base class or implementing well known interface:
public interface IWellKnown
{
int PropertyA { get; }
int PropertyB { get; }
}
Any your method will be:
public static int[] DoSomething<T> (T[] Input) where T : IWellKnown
{
int[] Output = new int[Input.Length];
for (int i = 0;i < Input.Length;i++)
Output[i] = Input[i].PropertyA+Input[i].PropertyB;
return Output;
}
Edit:
Creating generic method working with any numeric type but just with numeric types is imho not possible because .NET doesn't have any base type like Number. So you cannot limit generic type to numbers only. All numeric types are value types so you can do something like:
public interface IWellKnown<TData> where TData : struct
{
TData PropertyA { get; }
TData PropertyB { get; }
}
But in such case your interface will accept any value type - any custom structure, char, bool, etc.
Its not possible to create such an restriction. You should check the input at runtime and throw a helpful exception error message.
You can however do something like:
public interface IWellKnown
{
int PropertyA { get; }
int PropertyB { get; }
}
public abstract class WellKnownBase<T> : IWellKnown
{
IWellKnown.PropertyA { get { return Convert(this.PropertyA); } }
IWellKnown.PropertyB { get { return Convert(this.PropertyB); } }
public T PropertyA { get; }
public T PropertyA { get; }
protected virtual int Convert(T input) { return (int)input; }
}
Using such a base class guides the one implementing a concrete version to provide a way to cast to int. The explicit interface implementation provides access to int typed accessors while the "real" class still provides the original type.
public class WellKnownFloat : WellKnownBase<Float> {}
Would provide you with a class for float. If the type is not castable to int you can provide a custom converter:
public class WellKnownTimeSpan : WellKnownBase<TimeSpan>
{
protected override int Convert(TimeSpan input)
{
return (int)input.TotalMilliseconds;
}
}
By the way, using linq and adding the requirement to the interface you can rewrite your function to input.Select(x => x.PropertyA + x.PropertyB)).ToArray().
PS: please check the code using VisualStudio, I am just writing it out of my head without compiler support ;) There may be small compiletime errors.

How to implement a class to access objects of several different types in C#?

I'm trying to implement a class to access items of different types, in a similar way to database rows.
However, I have two different ideas in mind, and I don't know which one to choose:
Design 1
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
private object val;
public ObjectTypeA Type
{
get;
private set;
}
public int Integer
{
get
{
if (Type != ObjectTypeA.Integer) throw new Exception();
return (int)val;
}
set
{
Type = ObjectTypeA.Integer;
val = value;
}
}
public float Float
{
get
{
if (Type != ObjectTypeA.Float) throw new Exception();
return (float)val;
}
set
{
Type = ObjectTypeA.Float;
val = value;
}
}
}
Less compile-time checks possible.
Can't use the is operator, GetType(), etc. (reinvents the type system).
Boxing and unboxing for value types.
Can be inherited by other classes (e.g. I can create a "named object" using inheritance).
Design 2
public abstract class MyObjectB
{
}
public class MyIntegerB : MyObjectB
{
public int Value
{
get;
set;
}
public MyIntegerB(int _value)
{
Value = _value;
}
}
public class MyFloatB : MyObjectB
{
public float Value
{
get;
set;
}
public MyFloatB(float _value)
{
Value = _value;
}
}
Shorter and simpler implementation.
Very verbose (casting) to use.
Performance is not critical, but it's still important, since most of the objects that are going to be stored are integers or floats, so boxing overhead matters.
The classes will just contain the values, not methods that depend on the type, etc. so it doesn't matter if the solution uses inheritance.
IMPORTANT: One of the requirements is that there may be two types that use the same underlying type (e.g. two classes derived from MyObjectB may use int as the Value), so using object or generics may not be possible.
Any suggestion about which design to use, or another different design?
EDIT:
The reason I don't like the second one is because it's very verbose to use:
MyObjectB objB = new MyIntegerB(12);
Console.WriteLine(((MyIntegerB)objB).Value);
And because I can't inherit it to create something like a "named object", so I have to attach MyObjectB to the class, and the usage is even more verbose.
I don't see why you wouldn't use generics here. More strongly: I don't see why you need this at all: It seems like Nullable<T> would cover all of your use cases very nicely. If not, implementing this generically is trivial:
public class ValueWrapper<T>
{
public T Value
{
get;
private set;
}
public Type WrappedType
{
get { return typeof(T); }
}
}
public MySpecialInt : ValueWrapper<int>
{
/* etc */
}
why not use generics?
public abstract class MyObjectB<T>
{
public T Value
{
get;
set;
}
public MyObjectB(T _value)
{
Value = _value;
}
}
you only need one class at this point. just instantiate it differently:
var myObj = new MyObjectB<Int>(1);
or
var myObj = new MyObjectB<Float>(0.012);
I know you mentioned not wanting to deal with boxing and unboxing, but I still think a Generic class would be your best bet here.
public class MyObject<T>
{
public MyObject(T t) {
Value = t;
}
public T Value { get; set; }
}
Edit:
One of the requirements is that there
may be two types that use the same
underlying type (e.g. two classes
derived from MyObjectB may use int as
the Value), so using object or
generics may not be possible.
That would only apply if you're extending the class. There's no problem if you wrap the class instead, i.e. create a MyObject<int> and access its Value property, rather than subclassing it.
Having said that, if you want to subclass a generic class, the subclass would also need to be a generic class.
Have you considered generics?
public class MyObjectA<T> {
public T Value {
get; set;
}
}
I've written a similar class that could hold either a single instance of ClassX or an array of ClassX. The trick was that it could change during runtime, so a generic wouldn't suffice, but I still wanted it strong-typed in all cases. It sounds like that's similar to what you're trying to accomplish here.
I chose the first option, and here's why: Wherever possible, I encapsulate complexity within a class to make the class easier to use. Classes should encapsulate away complexity from the caller, making calls to it more concise. If using MyObjectB makes your code more verbose, than I don't think that's the right answer.
if you need heterogeneous collections then this would do.
public enum ObjectTypeA
{
Undefined,
Integer,
Float
}
public class MyObjectA
{
public MyObjectA(object value) : this(value, InfereType(value))
{ }
public MyObjectA(object value, ObjectTypeA type)
{
Value = value;
Type = type;
}
public object Value { get; private set; }
public ObjectTypeA Type
{
get;
private set;
}
public T ValueAs<T>()
{
return (T)Value;
}
}
then use it like
List<MyObjectA> list = GetAllValues();
foreach (var item in list)
{
switch (item.WrappedType)
{
case MyObjecttypeA.Float:
float f = item.ValueAs<float>();
// do something with float
}
}

Categories