C# question on what this code means - c#

I am learning c# code from one of the applications that I run SQL queries from.
I am wondering what the following code does in layman's terms:
return typeof(ViewModelBase<T>).GetProperty(propertyName) != null;
This is in a function that returns a boolean and a string is passed into it.
ViewModelBase<T> is an abstract class. Can someone also explain what the <T> does in this? I have ideas on these but I'm not sure what exactly is true.
Thanks!

The code returns true if the type has the property, and false if it doesn't.
This code will be written inside of a generic class, with a type parameter of T. In generics, each time a "hard" type is used with the generic class, the compiler creates a brand new concrete type. So for example, if there was code in your project that was using ViewModelBase<int>, ViewModelBase<string>, and ViewModelBase<MyType>, there would be three concrete types created in the final assembly by the compiler.
Each of these three hypothetical types would have properties and methods. The code shown above would (for all intents and purposes) be duplicated three times, with the type parameter "T" substituted with int, string and MyType in each of the three cases.
GetProperty() would then check to see if the concrete types had the property given in the "propertyName" variable, and return true or false accordingly.

That tells you whether or not the class type ViewModelBase<T>, based on the given type of T, has a public property with the same name as the value of propertyName.
Type.GetProperty() returns a PropertyInfo object if there's such a property; null otherwise. Hence the boolean comparison against null.

The code piece that you have there is part of a generic type, having a type argument T. Now, we don't see the full method, but I can imagine it looks something like so:
public static bool T HasProperty<T>(string propertyName)
{
return typeof(ViewModelBase<T>).GetProperty(propertyName) != null;
}
Let's say you have a class Customer:
class Customer
{
// implementation of class Customer goes here
}
Then you could call the HasProperty method like this:
bool itsThere = HasProperty<Customer>("SomePropertyName");
This means that the HasProperty method will return true if ViewModelBase<Customer> has a property called SomePropertyName, otherwise false.

This checks whether ViewModelBase<T> has a property with a name equal to propertyName.

Related

Casting to arbitrary non-generic return type at runtime, C#

I'm trying to make a user-friendly debug framework where users can create more debug variables as easily as possible.
I need to cast an object to the return type of my property/method (bool, int, whatever), without knowing what that return type is.
tldr: How can I return a non-generic type (in this example bool) from
public bool MyGetSetProperty {
get {
object obj = new object();
return (bool)obj;
}
}
WITHOUT specifying "return (bool)"? So something like
return (GenericThingHereThatPassesAsBool)obj;
or
return obj as MyGetSetPropertyReturnType;
----------
Detail:
I want users to be able to create new properties in this class as easily as possible - basically copying+pasting the whole code block below, and only replacing "SerializeAll" with their variable name, and the type declaration "bool" with the type they want on the field/property declarations.
In my getter, I have a couple separate checks to see if the entire debug system is enabled. If not, it returns a default value for the given variable.
[Tooltip ("Serialize ALL XML output fields?"), SerializeField]
private bool debugSerializeAll = false;
/// <summary>
/// Serialize ALL XML output fields?
/// </summary>
[DebugValue, DebugDefault (true)]
public bool SerializeAll {
get {
if (!classEnabled || !debug.debugEnabled)
return (bool)GetDefaultValue (MethodBase.GetCurrentMethod ());
return debugSerializeAll;
}
set { debugSerializeAll = value; }
}
The thing is, I can't return "default" because the default value can be overridden - see the "DebugDefault" attribute where the "default" value for this bool is actually "true", at least as far as my debug system is concerned. The method "GetDefaultValue" accommodates for that, and it returns an object that could be a string, int, bool, anything.
I'm already doing funky reflection stuff to access the MethodInfo, PropertyInfo, etc of the getter and property SerializeAll. I just can't figure out how to not have to also specify the (bool) cast on the return. Again, the goal is as little human editing as possible.
Thank you!
You should be able to do this with a cast to dynamic.
return (dynamic)GetDefaultValue (MethodBase.GetCurrentMethod ());
Bear in mind that the compiler isn't actually making this into a cast to bool. Rather, this makes the compiler ignore compile-time type-safety, and instead the program will use reflection at runtime to figure out the best way to take the value returned from GetDefaultValue and turn it into what it needs to be.
I want users to be able to create new properties in this class as easily as possible...
This is a good principle.
... basically copying+pasting the whole code block below, and only replacing "SerializeAll" with their variable name, and the type declaration "bool" with the type they want on the field/property declarations.
That totally breaks the principle you just mentioned, and results in a bunch of boilerplate code and other code smells.
In theory, you could probably create a Fody Weaver or something to add this boilerplate code upon compilation. But that's probably more work than it's worth.
I would hazard a guess that this is an "XY Problem", where you're asking how to achieve the solution that you've imagined, rather than asking how to solve the problem you're actually facing.
Why should every property in your class return a completely different value if certain private fields are set a certain way? This sounds like a big Separation of Concerns problem, where you're tasking your class with doing two completely different things. I strongly suggest you find another way to solve the problem you're trying to solve. For example, when code tries to get an instance of your class, it could go through a method that checks the classEnabled and debug.debugEnabled concepts (which probably belong in a different class), and returns an instance with the properties all set to their defaults.
Please Link click here -> How to cast Object to boolean?
or
I think you need to study for Generic class
Check if a class is derived from a generic class

What type is inside a generic container

public T getValueByName<T>(String name)
{
if( T is List )
Object containedType = T.WhatGoesHere()?
...
In the above code, I need to know if I can convert a List to whatever type of list is passed in, e.g., List<Control>.
Is there a way to interrogate the generic for the contained type? I could get List<Control>, List<String>, List<Form> etc..
I could split the API to return lists in a separate method where the contained type is passed in, thus requiring the caller to use one method for lists and one for simple types. Either way they have to know what's coming back, but if there's a smooth way to do what I'm asking about, I'd rather keep the API simple.
Note: this is a solution to the lack of covariance because even though there is an implicit conversion operator defined on the contained type, a cast of List to T fails. So, in order to follow the solution listOfB.Cast<A>(); from here, I need to know to what to cast (what is A).
Thanks!
You can start with typeof(T) to get an instance of System.Type that represents T.
Once you have that, you can check Type.IsGenericType to see if it really is a generic and then call Type.GetGenericArguments() to see what generic arguments were used.
For example, if T was List<int> IsGenericType would be true and GetGenericArguments() would return an array containing one element: System.Int32
For example, here is a snippet of code I wrote to see if a given type (variable type) is some implementation if IEnumerable<T> where T is not known. It first has to see if it is a generic, then work out whether it has only one argument, determine said argument and see if it implements the interface, given that argument:
if (type.IsGenericType)
{
Type[] genericArguments = type.GetGenericArguments();
if (genericArguments.Length == 1)
{
Type proposedEnumerable = typeof(IEnumerable<>).MakeGenericType(genericArguments);
if (proposedEnumerable.IsAssignableFrom(type))
{
For reference, see:
http://msdn.microsoft.com/en-us/library/system.type.isgenerictype(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/system.type.getgenericarguments(v=vs.110).aspx

General Generics c#

So I have this test program:
namespace ConsoleApplication1TEST{
class Program
{
static void Main(string[] args)
{
new derp<int,int>(5,4);
}
}
class derp<T,V>
{
public T top;
public V vop;
public derp(T to, V vo)
{
top = to;
vop = vo;
top.ToString();
}
}
}
top.ToString is allowed. As are GetHashCode, GetType, and Equals. However, ToUpper is not allowed, and neither are other string-specific methods. Can this be changed?
When I place a method that is not allowed, this is the error I get:
Error 1 'ConnectionServiceT' does not contain a definition for
'connect' and no extension method 'connect' accepting a first argument
of type 'ConnectionServiceT' could be found (are you missing a using
directive or an assembly reference?)
top.ToString is allowed. GetHashCode, GetType, Equals is also allowed.
However, ToUpper is not allowed, and other string-specific methods are not allowed. Can this be changed?
That's perfectly normal. The compiler knows nothing about the actual type of T, so it can't assume that it has a ToUpper method. However, since all types (except pointers) inherit from Object, calling methods of the Object class is allowed.
Now, if there was a constraint on T to force it to inherit a type that has a ToUpper method, your code would work:
class derp<T,V> where T : String
It's a bad example, because String is sealed, so this code wouldn't compile, but it's just to illustrate the idea.
Anyway, if you want to be able to call the String.ToUpper method on top, then the type of top cannot be generic: it has to be String.
To learn more about generic constraints, see MSDN: http://msdn.microsoft.com/en-us/library/d5x73970.aspx
It is reasonable that the method ToUpper() is not allowed, since this is a method specific for string types. If your type isn't a string then you can't use the ToUpper() method, because this method is specific to string types.
On the other hand, since all types inherrit the object type, they inherit it's methods, which are ToString(), GetHashCode(), GetType() and Equals().
This is a good link regarding the inheritance in C#, in where you can see more thoroughly what I am talking about.
Also here is stated that:
In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from Object.
.ToString() works on every type. If the type is not a string the type's name will be returned.
.ToUpper() is a string specific, won't work on types other than string.
Can this be changed?
You don't know what T and V are, so the only assumption the compiler can make is that they inherit from object, which is why ToString, GetHashCode, GetType, and Equals are allowed (since they're methods on object which every class inherits from).
If ConnectionServiceT (and other similar classes) inherit from a base class you can constrain T and V to be subclasses of a given type:
class derp<T,V> where T:BaseService
where V:MyOtherClass
{
public T top;
public V vop;
public derp(T to, V vo)
{
top = to;
vop = vo;
top.ToString();
}
}
Then you can call methods specific to BaseService on instances of T (since you know that T must derive from BaseService.
But you can't constrain to string because it's sealed - the only possible class would be derp<string, string> so there's no reason to use generics.
It is a good thing you cant use ToUpper(). You are sending in integers, those certainly do not have a ToUpper method. ToUpper is a method that belongs to string objects. You could do this:
string myUpperCaseString = top.ToString().ToUpper();
//or
if(top.GetType() == typeof(string)
{
string myUpperCaseString = (top as string).ToUpper();
}
What you may have been mistaken about, is that ToString() does not change the string... it instead returns a new string representation of that object, you then have to store this object somewhere. Above I stored it in a variable called myUpperCaseString with the type of string.
ToString, GetHashCode, GetType are all methods that belong to the object class and anything that inherits from it.

Some misunderstanding in ChangeType method

I'm a newer in c# so maybe my question will seem naive to some of you.
I'm using this method:
public static object ChangeType(object value, Type conversionType);
From metadata manual:
Returns:
An object whose type is conversionType and whose value is equivalent
to value.-or-A
null reference (Nothing in Visual Basic), if value is null and conversionType
is not a value type.
But in method signature the returned type always 'object'. So, what is the benefit in converting the value if returned type is object?
Convert.ChangeType creates a new object of the specified type, with a value equivalent to the object you passed.
For example, Convert.ChangeType("42", typeof(int)) will return a boxed int instance rather than a string.
The actual behavior is completely within the IConvertible implementation of the object you pass.
The reason is that you can cast to your particular type. This method comes from before generic types so the only way it could return one of any number of types is by returning the supertype of all of them, ie object. You can of course then cast that to your chosen type and guarantee you will be successful but the only other option would be an overload of every single type ever which would be a bit weighty. :)
The thing to note is that this isn't just the same as casting. It will return a whole new object which is the type you asked for rather than the type you gave it.
Also,
from the msdn documentation: http://msdn.microsoft.com/en-us/library/aa324833(v=vs.71).aspx
*
value An Object that implements the IConvertible interface.
*
In .net methods have a fixed signature (with generics you can go further, but that's not the case here) - so for this conversion method they chose the most common type: object.
Consider Person and Man. Man is defined as
class Man : Person
In order to create an address book, you would not create two methods:
Man GetByName(string name);
Woman GetByName(string name);
Instead you would create one method:
Person GetByName(string name);
This method would return a Person and even though the actual object returned is a Man, all you currently know about it is that it's a Person.
Back to the converter: you know the return type as you supplied it in the parameters, but a long time ago when the method was created they did not know what you were going to supply as parameter. You can safely cast the result to the type you already know:
MyType myObject = (MyType)ChangeType(value, typeof(MyType));

Working with an unknown number of unknown types - .NET

hey guys, I've removed some of the complexities of my needs to the core of what I need to know.
I want to send a collection of Values to a method, and inside that method I want to test the Value against, say, a property of an Entity. The property will always be of the same Type as the Value.
I also want to test if the value is null, or the default value, obviously depending on whether the value type is a reference type, or a value type.
Now, if all the values sent to the method are of the same type, then I could do this using generics, quite easily, like this:
public static void testGenerics<TValueType>(List<TValueType> Values) {
//test null/default
foreach (TValueType v in Values) {
if (EqualityComparer<TValueType>.Default.Equals(v, default(TValueType))) {
//value is null or default for its type
} else {
//comapre against another value of the same Type
if (EqualityComparer<TValueType>.Default.Equals(v, SomeOtherValueOfTValueType)) {
//value equals
} else {
//value doesn't equal
}
}
}
}
My questions is, how would I carry out the same function, if my Collection contained values of different Types.
My main concerns are successfully identifying null or default values, and successfully identifying if each value passed in, equals some other value of the same type.
Can I achieve this by simply passing the type object? I also can't really use the EqualityComparers as I can't use generics, because I'm passing in an unknown number of different Types.
is there a solution?
thanks
UPDATE
ok, searching around, could I use the following code to test for null/default successfully in my scenario (taken from this SO answer):
object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;
I reckon this might work.
Now, how can I successfully compare two values of the same Type, without knowing their types successfully and reliably?
There is Object.Equals(object left, object right) static method, it internally relies on Equals(object) implementation available at one of provided arguments. Why do you avoid using it?
The rules of implementing equality members are nearly the following:
Required: Override Equals(object) and GetHashCode() methods
Optional: Implement IEquatable<T> for your type (this is what EqualityComparer.Default relies on)
Optional: Implement == and != operators
So as you see, if you'll rely on object.Equals(object left, object right), this will be the best solution relying on strongly required part of equality implementation pattern.
Moreover, it will be the fastest option, since it relies just on virtual methods. Otherwise you'll anyway involve some reflection.
public static void TestGenerics(IList values) {
foreach (object v in values) {
if (ReferenceEquals(null,v)) {
// v is null reference
}
else {
var type = v.GetType();
if (type.IsValueType && Equals(v, Activator.CreateInstance(type))) {
// v is default value of its value type
}
else {
// v is non-null value of some reference type
}
}
}
}
The short answer is "yes", but the longer answer is that it's possible but will take a non-trivial amount of effort on your part and some assumptions in order to make it work. Your issue really comes when you have values that would be considered "equal" when compared in strongly-typed code, but do not have reference equality. Your biggest offenders will be value types, as a boxed int with a value of 1 won't have referential equality to another boxed int of the same value.
Given that, you have to go down the road of using things like the IComparable interface. If your types will always specifically match, then this is likely sufficient. If either of your values implements IComparable then you can cast to that interface and compare to the other instance to determine equality (==0). If neither implements it then you'll likely have to rely on referential equality. For reference types this will work unless there is custom comparison logic (an overloaded == operator on the type, for example).
Just bear in mind that the types would have to match EXACTLY. In other words, an int and an short won't necessarily compare like this, nor would an int and a double.
You could also go down the path of using reflection to dynamically invoke the Default property on the generic type determined at runtime by the supplied Type variable, but I wouldn't want to do that if I didn't have to for performance and compile-time safety (or lack thereof) reasons.
Is the list of types you need to test a pre-determined list? If so, you can use the Visitor Pattern (and maybe even if not since we have Generics). Create a method on your Entities (can be done using partial classes) that takes in an interface. Your class then calls a method on that interface passing itself. The interface method can be generic, or you can create an overload for each type you want to test.
Battery about to die otherwise would give example.
Fifteen seconds after hitting "Save" the machine went into hibernate.
After thinking about it, the Visitor pattern might not solve your specific problem. I thought you were trying to compare entities, but it appears you are testing values (so potentially ints and strings).
But for the sake of completion, and because the visitor pattern is kind of cool once you realize what it does, here's an explanation.
The Visitor pattern allows you to handle multiple types without needing to figure out how to cast to the specific type (you decouple the type from the item using that type). It works by having two interfaces - the visitor and the acceptor:
interface IAcceptor
{
void Accept(IVisitor visitor);
}
interface IVisitor
{
void Visit(Type1 type1);
void Visit(Type2 type2);
.. etc ..
}
You can optionally use a generic method there:
interface IVisitor
{
void Visit<T>(T instance);
}
The basic implementation of the accept method is:
void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
Because the type implementing Accept() knows what type it is, the correct overload (or generic type) is used. You could achieve the same thing with reflection and a lookup table (or select statement), but this is much cleaner. Also, you don't have to duplicate the lookup among different implementations -- various classes can implement IVisitor to create type-specific functionality.
The Visitor pattern is one way of doing "Double Dispatch". The answer to this question is another way and you might be able to morph it into something that works for your specific case.
Basically, a long-winded non-answer to your problem, sorry. :) The problem intrigues me, though -- like how do you know what property on the entity you should test against?

Categories

Resources