BaseType of a Basetype - c#

this is my first question here so I hope I can articulate it well and hopefully it won't be too mind-numbingly easy.
I have the following class SubSim which extends Sim, which is extending MainSim. In a completely separate class (and library as well) I need to check if an object being passed through is a type of MainSim. So the following is done to check;
Type t = GetType(sim);
//in this case, sim = SubSim
if (t != null)
{
return t.BaseType == typeof(MainSim);
}
Obviously t.BaseType is going to return Sim since Type.BaseType gets the type from which the current Type directly inherits.
Short of having to do t.BaseType.BaseType to get MainSub, is there any other way to get the proper type using .NET libraries? Or are there overrides that can be redefined to return the main class?
Thank you in advance

There are 4 related standard ways:
sim is MainSim;
(sim as MainSim) != null;
sim.GetType().IsSubclassOf(typeof(MainSim));
typeof(MainSim).IsAssignableFrom(sim.GetType());
You can also create a recursive method:
bool IsMainSimType(Type t)
{ if (t == typeof(MainSim)) return true;
if (t == typeof(object) ) return false;
return IsMainSimType(t.BaseType);
}

if (sim is MainSim)
is all you need. "is" looks up the inheritance tree.

Use the is keyword:
return t is MainSim;

The 'is' option didn't work for me. It gave me the warning; "The given expression is never of the provided ('MainSim') type", I do believe however, the warning had more to do with the framework we have in place. My solution ended up being:
return t.BaseType == typeof(MainSim) || t.BaseType.IsSubclassof(typeof(MainSim));
Not as clean as I'd hoped, or as straightforward as your answers seemed. Regardless, thank you everyone for your answers. The simplicity of them makes me realize I have much to learn.

How about "is"?
http://msdn.microsoft.com/en-us/library/scekt9xw(VS.71).aspx

Related

Creating an ambiguous test

I had an idea about creating a bool isNull that can be used pretty much ambiguously wherever needed. The original idea was as follows (pseudo-code only):
bool isNull(var test)
{
if (test == null || DBNull || string.Empty)
return true;
else
return false;
}
But this doesn't work, as var is not recognised here. Instead, it appears to be assumed that var refers to a type... well I, of course, don't have a type for var!
What do I do to get around this? Or, perhaps the question I should be asking, Is this a good idea at all?
Why don't you use object ?
bool isNull(object test)
{
if (test == null || test == DBNull.Value)
return true;
else
return false;
}
For strings, I would use string.IsNullOrEmpty method.For other types, especially when you are dealing with databases this function can be useful.
Your code isn't working because var will be resolved at compile-time.
You could use object or dynamic as type. dynamic will be resolved at run-time

CodeType get generic parameters

We're using the Visual Studio CodeModel and have some problems to get the generic parameters of a CodeType. How to obtain them without parsing the FullName ourselves?
It is hinted (although not marked an answer) in How can I get the generic constraints from CodeInterface as a CodeType object? that there is no other way, however, this is not really believable as:
System.Func<Outer.Inner>
would not be defined: You cannot know if the generic parameter you've parsed (Outer.Inner) is referring to the namespace Outer containing a class Inner or if it is referring to the class Outer having an inner class Inner (and yes, it is not Outer+Inner in such cases).
If somebody at least knows how to tell the FullName property to show nested classes with a + sign this would be great too.
I think the answer here is pretty definitive. This isn't supported by DTE or DTE2 and is unlikely to be supported in the future.
The only way currently is to use Roslyn, which is not acceptable for those of us that don't want to use pre-release software. I also haven't looked into what kinds of dependencies that will entail (do users of my component need to install Roslyn?).
You could use a regular expression to get the types from the FullName string. But, for those of us in the real world who need the token (T) to concrete type (System.String) mapping, this is not an option.
I can't find a way to do it for any generic type, but if you need to do it for a specific type, it is possible in some cases.
For instance, I have the following code to check if a type is a collection, and if it is, get the element type:
private static bool IsCollectionType(CodeType type, out CodeType elementType)
{
// string implements IEnumerable<char>, but we don't want to treat it as a collection
if (type.FullName == "System.String")
{
elementType = null;
return false;
}
var enumerable = type.Bases.OfType<CodeInterface>().FirstOrDefault(i => i.FullName.StartsWith("System.Collections.Generic.IEnumerable<"));
var method = enumerable?.Members.OfType<CodeFunction>().FirstOrDefault(m => m.Name == "GetEnumerator");
var enumerator = method?.Type.CodeType;
var current = enumerator?.Members.OfType<CodeProperty>().FirstOrDefault(m => m.Name == "Current");
if (current != null)
{
elementType = current.Type.CodeType;
return true;
}
elementType = null;
return false;
}
As you can see, I'm not directly looking at the generic type argument, but instead I look at the type of IEnumerable<T>.GetEnumerator().Current. Of course, this requires specific knowledge about the type you're working with.

Simulating operator like "inverse of ??"

a ?? b
If a is not null => returns a.
Else (a is null) => returns b.
I want to simulate something like its inverse (AFAIK there is no operator to do this):
If a is null => return a.
Else (a is not null) => returns b.
The idea is that b would be the result of a function that receives a and needs to avoid null parameters. Like this: a XX fn(a) where XX would be the operator (if it exists).
My only two variants are:
a == null ? a : fn(a)
a == null ? null : fn(a)
Is there any way to simplify this code?
Not sure exactly what you're trying to accomplish? Something like this?
TResult NullFn<TParam, TResult>(TParam a, Func<TParam, TResult> method)
{
if(a == null) return null;
return method(a);
}
...
var result = NullFn(a, a => fn(a))
But the best solution IMHO would be to just have fn return null if it is passed a null value.
EDIT:
The method at the top is only an example. You might want to use something like this in a situation where you've got a LOT of the same operation over and over again in a specific area and you can't change fn because it would make is easier to focus on the rest of the code and there's a chance you might want to alter the null-handling behavior for all your operations at once in the future. (I'm assuming that is the case because you're asking in the first place.) But I wouldn't use this across an entire application because it isn't clear what's happening if you don't have the NullFn function right in front of you.
Whats wrong with simple condition?
if (a != null) b = fn(a);
Another option - add a condition to your method:
public B fn(A a)
{
if (a == null)
return null;
return new B();
}
Personally I would prefer
(a != null) ? fn(a) : null
because I think it makes the intention more obvious, but I can not think of a way to simplify that much. You could use an extension method if you like.
a.CallIfNotNull(fn)
with the following extension method
internal static T CallIfNotNull<T>(this T value, Func<T, T> function)
where T : class
{
return (value != null) ? function(value) : null;
}
Not really better but probably less error prone and easier to type given IntelliSense.
(Is assumed the function returns a value of the same type as the argument as the question suggests.)
If you have T a; and T fn(T a); using the same user-defined type T, then you can write a && fn(a) and it will expand to T.False(a) ? a : T.&(a, fn(a)).
You've answered your own question with the ?: implementations at the bottom.
The only improvement i would suggest is to wrap the functionality in a method that makes it cleaner and less error prone to do.
object SafeB(object a)
{
return a==null ? a : b(a);
}
The compiler will probably inline this so you won't lose performance.
You may even be able to implement it as an extension method of the class that provides b so that it becomes an even more integrated solution.

Test generic type parameter for interface

I have a generic method (see code below) and want to perform some action if T is a particular interface.
Obviously I could just do a typeof(T).IsAssignableFrom(IFoo) but reflection is comparatively slow so I want to avoid it if possible.
Now, I know I can't have another method with the a constraint because I'd get the ambiguous method error otherwise I'd just do that.
Is there a way of doing what I want?
Does the fact that I want to do this point to some architectural problem?
public T Load<T>(string name)
{
T result = LoadFromName<T>(name);
if(T is IFoo) // Obviously doesn't work as T is a type, not a variable
(result as IFoo).FooMethod();
return result;
}
But you have got a variable - result! What's wrong with
var asFoo = result as IFoo;
if (asFoo != null)
asFoo.FooMethod();

What's the right way to check for inheritance from a class/interface?

The code below is looping through a dictionary of strings and IMyCompanySettings looking for values that implement IMyCompanyProductSetting. Clearly, trying to cast and raising an exception is a very expensive way to do this.
public static List<IMyCompanyProductSetting> GetProductSettings(ConfigurationManager cfm)
{
List<IMyCompanyProductSetting> ret = new List<IMyCompanyProductSetting>();
foreach(IMyCompanySetting setting in cfm.Values)
{
try
{
IMyCompanyProductSetting prod = (IMyCompanyProductSetting)setting;
ret.Add(prod);
}
catch
{
// Do nothing.
}
}
return ret;
}
What's a better way to do this?
Casting 101 [general info on casting stuff]:
Use [object] is [interface/class] expression:
if (setting is IMyCompanyProductSetting) {
...
}
Alternatively you can use the as keyword which tries to cast the object and if it fails, instead of throwing exception, it'll return null. Note that the target type must be a reference type in the as keyword:
var prod = setting as IMyCompanyProductSetting;
if (prod != null) {
...
}
You should always use the above code instead of the equivalent exception handling.
Filtering an IEnumerable by type (LINQy):
As Jon Skeet pointed out, you should use OfType extension method to filter a sequence easily (assuming you got LINQ):
var filteredSequence = sequence.OfType<TargetType>();
Casting an IEnumerable to type (LINQy):
If you want to try casting each element to the target type (as opposed to filtering by type), you can use the Cast extension method:
var castedSequence = sequence.Cast<TargetType>();
The "hard" way (pre-LINQ) is to use "as". This is more efficient than using "is" and then casting each time (as both the "is" and the cast require execution-time checks):
IMyCompanyProductSetting prod = setting as IMyCompanyProductSetting;
if (prod != null)
{
ret.Add(prod);
}
See another question for when to use "as" and when to use a cast.
If you're using .NET 3.5, however, it's really easy:
return cfm.Values.OfType<IMyCompanyProductSetting>().ToList();
Very easy :)
Mehrdad has the answer. I'll only add that you should never use that "try / catch everything" trick. At best in that case, you're trying to catch an InvalidCastException. You wouldn't want to ignore some other exception, possibly from the execution of the method you're trying to call.
You should use the 'Is' statement instead for more concise and less error prone code. See the example below.
if (setting Is IMyCompanyProductSetting)
ret.add((IMyCompanyProductSetting)setting);
Either do
if (setting is IMyCompanyProductSetting)
{
IMyCompanyProductSetting prod = (IMyCompanyProductSetting)setting;
}
or
IMyCompanyProductSetting prod = setting as IMyCompanyProductSetting;
if (setting != null)
{
}

Categories