CA1004 and exception/error handling assistance - c#

CA1004: Generic methods should provide type parameter
public static void IfNullAndNullsAreIllegalThenThrow<T>(object value)
{
if (value == null && !(default(T) == null))
throw new ArgumentException("Nulls are not allowed for this object.");
}
I found this method online, which is quite useful to be honest. But, it violates the CA1004 rule. I'm not sure if there is a better way to design the method and not violate the rules.
Sample usage:
public class SomeClass<T>
{
public void SomeMethod(object obj)
{
// Ensure the actual object is not null if it shouldn't be.
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(obj);
// ...
}
}

This looks like a helper method which is only used internally. Make it internal instead of public and the warning should go away.

CA1004 is warning you that the generic type parameter cannot be inferred from the method's signature. Basically, it means you can only call it like this:
Something obj = GetSomething();
IfNullAndNullsAreIllegalThenThrow<Something>(obj);
On the other hand, if you redefine the method so its argument is of type T, then the generic type parameter can be inferred from the object passed:
public static void IfNullAndNullsAreIllegalThenThrow<T>(T value)
{
if (value == null && !(default(T) == null))
throw new ArgumentException("Nulls are not allowed for this object.");
}
So you can simply write:
Something obj = GetSomething();
IfNullAndNullsAreIllegalThenThrow(obj);

Related

Implicit conversion from null

Looking Zoran Horvats courses at PluralSight, I'm currently implementing a Maybe type, a bit like Zoran has on its GitHub account: https://github.com/zoran-horvat/option
Generally, a Maybe is a wrapper around objects, which are either set or have a null value, avoiding null reference exceptions.
To make the code a bit shorter, I would like to use implicit conversion to map the values / nulls to their corresponding maybe types. Here an example of my code:
public void Hook(Maybe<Action<Keys>> onKeyDown, Maybe<Action<Keys>> onKeyUp)
{
_keyDownCallback = onKeyDown;
_keyUpCallback = onKeyUp;
_hookService.Hook(HookType.KeyBoardLowLevel, OnHookReceived);
}
As you can see, you can hook and pass two optional callbacks, one for keyDown and one for keyUp. I would like to pass code like this:
nativeKeyboardHookService.Hook(new Action<Keys>(OnNativeKeyDown), null);
The implicit conversion on the Maybe is currently implemented like this:
public static implicit operator Maybe<T>(T value)
{
return ToMaybe(value);
}
public static implicit operator T(Maybe<T> maybe)
{
return ToT(maybe);
}
public static Maybe<T> ToMaybe(T value)
{
if (value == null)
{
return new None<T>();
}
return new Some<T>(value);
}
public static T ToT(Maybe<T> maybe)
{
return maybe.Evaluate(
value => value,
() => default(T));
}
My question: It works fine, if I pass an actual object, mapping it to an Maybe, but if I pass NULL, I still get a NULL object, not a None object. Am I doing here something wrong or is it just not possible? I didn't find any further information regarding such a conversion.
When you pass null to Hook() that's literally all you are doing because your implicit casts aren't being invoked at all. That's because null is a valid value for a reference type, and thus no need to cast.
You can't change Maybe to a struct if you want to keep Some and None because then these would have to be structs too, which means you run into the issue that you can't inherit structs.
You can't implement a common IMaybe<T> interface either because interfaces can't be used with casts.
What I recommend is keep your behavior as is, but don't use null. Instead of passing null, pass something else like Maybe<T>.None:
class Maybe<T>
{
public static Maybe<T> None { get; } = new None<T>();
}
void Hook(..., Maybe<T>.None) { ... }
Or None<T>.Instance:
class None<T>
{
public static None<T> Instance{ get; } = new None<T>();
}
void Hook(..., None<T>.Instance) { ... }
This has the advantage of being more readable and explicit.
Your Maybe<T> is still a reference type, so null is a valid value for it:
Maybe<string> foo = null;
If you want to prevent that, you will need to make it a value type, for example something like this:
public struct Maybe<T>
{
public T Value { get; }
public bool IsEmpty => Value == null;
public Maybe(T value)
{
Value = value;
}
public static implicit operator Maybe<T>(T value)
{
return new Maybe<T>(value);
}
}
Then you can pass null to a method expecting a Maybe<T> and it will properly construct an empty Maybe<T> object.
But note that it being a value type, this now means that it is copied on every method call, so it has a different behavior to a reference type implementation.
In the end, you cannot really implement this nicely in C# simply because there is the null reference in the language. It’s only with C# 8’s nullable reference types that you will be able to prevent nulls altogether.

Determine if object is an instance of a generic base class, any generic type

I need to test if a value is an instance of a generic base class, without knowing the generic type parameter. Using the MSDN example as the base of my example, this is what I'd like to accomplish:
using System;
public class Class1<T> { }
public class DerivedC1 : Class1<int> { }
class IsSubclassTest
{
public static void Main()
{
Console.WriteLine(
"DerivedC1 subclass of Class1: {0}",
typeof(DerivedC1).IsSubclassOf(typeof(Class1<>)) // <- Here.
);
}
}
While this is syntactically correct, it always yields false. If I remove the generic type parameter, it works as expected (returns true).
How can I test if a class type is a subclass of a generic base class, without knowing its generic type parameter as such?
The problem is that DrevidedC1 is not a sublcass of Class1<T>, it's a subclass of Class1<int>. Make sure you understand this subtle diference; Class1<T> is a open type (T can be anything, it hasn't been set) while DerivedC1 extends a closed type Class1<int> (it's not open in T anymore, T is set to int and only int). So when you do the following:
typeof(DerivedC1).IsSubclassOf(typeof(Class1<>))
The answer is evidently false.
What you need to do is check if the generic type definition of DerivedC1's base type (think of it as the corresponding open generic type of Class1<int>) equals Class1<T> which it clearly does.
The correct code is therefore:
typeof(DerivedC1).BaseType.GetGenericTypeDefinition() == typeof(Class1<>));
Or better yet, as Matías Fidemraizer states in his answer:
typeof(DerivedC1).BaseType.GetGenericTypeDefinition().IsAssignableFrom(typeof(Class1<>)));
There's special methods on Type for this sort of thing. As far as I can see, you'll need to walk up your base-types and check each in turn until you either (a) hit a match or (b) get to the top of the inheritance hierarchy (i.e. System.Object).
As such, the following (recursive) extension method:
public static class TypeExtensions
{
public static bool IsDerivedFromGenericParent(this Type type, Type parentType)
{
if(!parentType.IsGenericType)
{
throw new ArgumentException("type must be generic", "parentType");
}
if(type == null || type == typeof(object))
{
return false;
}
if(type.IsGenericType && type.GetGenericTypeDefinition() == parentType)
{
return true;
}
return type.BaseType.IsDerivedFromGenericParent(parentType)
|| type.GetInterfaces().Any(t=>t.IsDerivedFromGenericParent(parentType));
}
}
will allow you to do the following
typeof(DerivedC1).IsDerivedFromGenericParent(typeof(Class1<>))
...and will also work if you test something derived from DerivedC1.
Changing typeof(DerivedC1).IsSubclassOf(typeof(Class1<>)) to typeof(Class1<>).IsAssignableFrom(typeof(DerivedC1).BaseType.GetGenericTypeDefinition()) should be enough in your case.
Type.IsAssignableFrom is more powerful than using Type.IsSubClassOf because it just checks if some type is assignable to other type. This includes, the same type, interface types and other cases.

Check if object is of non-specific generic type in C#

Say I have the following class:
public class General<T> { }
And I want to find out if an object is of that type.
I know I can use reflection to find out whether the object is of that generic type with Type.GetGenericTypeDefinition, but I want to avoid that.
Is it possible to do something like obj is General<T>, or obj.GetType().IsAssignableFrom(typeof(General<T>))?
I'm quite surprised that I couldn't find a similar question, although I may have used wrong keywords in my searches.
You can do this:
var obj = new General<int>();
var type = obj.GetType();
var isGeneral =
(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(General<>)) ||
type.GetBaseTypes().Any(x => x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(General<>));
Where GetBaseTypes is the following extension method:
public static IEnumerable<Type> GetBaseTypes(this Type type)
{
if (type.BaseType == null) return type.GetInterfaces();
return new []{type}.Concat(
Enumerable.Repeat(type.BaseType, 1)
.Concat(type.GetInterfaces())
.Concat(type.GetInterfaces().SelectMany<Type, Type>(GetBaseTypes))
.Concat(type.BaseType.GetBaseTypes()));
}
credits to Slacks answer
There are many answers to similar questions, but they all require reflection to walk up the type hierarchy. I suspect there is no better way. If performance is critical, caching the result maybe an option. Here is an example using a ConcurrentDictionary as a simple cache. Then the cost is reduced to a simple type lookup (via GetType) and a ConcurrentDictionary lookup after the cache has been initialized.
using System.Collections.Concurrent;
private static ConcurrentDictionary<Tuple<Type,Type>, bool> cache = new ConcurrentDictionary<Tuple<Type,Type>, bool>();
public static bool IsSubclassOfRawGeneric(this Type toCheck, Type generic) {
var input = Tuple.Create(toCheck, generic);
bool isSubclass = cache.GetOrAdd(input, key => IsSubclassOfRawGenericInternal(toCheck, generic));
return isSubclass;
}
private static bool IsSubclassOfRawGenericInternal(Type toCheck, Type generic) {
while (toCheck != null && toCheck != typeof(object)) {
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur) {
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
And you would use it like this:
class I : General<int> { }
object o = new I();
Console.WriteLine(o is General<int>); // true
Console.WriteLine(o.GetType().IsSubclassOfRawGeneric(typeof(General<>))); //true
Generic type definitions that are instantiated with type parameters have no relation at all to other generic type instantiations. They also have no relation to the generic type definition. They are completely incompatible when it comes to assignment and runtime casting. If they weren't it would be possible to break the type system.
For that reason runtime casts will not help. You will indeed have to resort to Type.GetGenericTypeDefinition. You can abstract that into a helper function and keep your code relatively clean that way.
If a generic class or interface has members which could be used by code which held a reference in a more general form like Object but didn't have the actual generic type available, such members should be exposed in a non-generic base class or interface. The Framework has in many cases failed to abide by that principle, but there's no reason one must follow their example. For example, a type like IList<T> could have derived from IListBase which included or inherited members like:
int Count {get;}
void Delete(int index);
void Clear();
void Swap(int index1, int index2);
int Compare(int index1, int index2);
// Return an object with a `StoreToIndex(int)` method
// which would store it to the list it came from.
ListItemHolder GetItemHolder(int index);
ListFeatures Features {get;}
None of those members would rely in any way upon the type of items held within the list, and one could write methods to do things like sort a list (if its Features indicated that it was writable and knew how to compare items) without having to know anything about the element type. If a generic interface inherits from a non-generic interface, code needing the non-generic functions could simply cast to the non-generic interface type and use it directly.
For a more generalized solution, that works with any parent type (base class as well as interfaces):
public static bool IsCompatibleWith(this Type type, Type parentType)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (parentType.IsAssignableFrom(type))
{
return true;
}
return type.GetAssignableTypes()
.Where(t => t.IsGenericType)
.Any(t=> t.GetGenericTypeDefinition() == parentType);
}
/// <summary>
/// Gets all parent types including the currrent type.
/// </summary>
public static IEnumerable<Type> GetAssignableTypes(this Type type)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
// First check for interfaces because interface types don't have base classes.
foreach (Type iType in type.GetInterfaces())
{
yield return iType;
}
// Then check for base classes.
do
{
yield return type;
type = type.BaseType;
}
while (type != null);
}
Come up with better method names. Perhaps calling it IsCompatibleWith is misleading. Maybe IsKindOf ? Also, GetAssignableTypes can also be called GetParentTypes but that is also misleading. Naming is hard. Documenting it is better.
Some tests:
IsCompatibleWith(typeof(List<int>), typeof(IList<int>))
true
IsCompatibleWith(typeof(List<>), typeof(IList<>))
true
IsCompatibleWith(typeof(List<int>), typeof(IList<>))
true
IsCompatibleWith(typeof(List<int>), typeof(IList<string>))
false

Creating an empty generic object [duplicate]

This question already exists:
Closed 10 years ago.
Possible Duplicate:
How do I compare a generic type to its default value?
I have a generic function that needs to test if the object that is passed into it is empty or not. But because its a generic type, the compiler doesnt know if a class or a struct is passed. Because of this I cant test for null I have to test if the type is empty.
public virtual void SetFocusedObject(T obj)
{
//since we dont know if T is a class or a struct test against default
T defaultT = default(T);
if(obj != defaultT)
{
//code
}
}
This does not work and its because the compiler doesnt know what T is to be able to compile the test
alternatively I tried the following as well
public virtual void SetFocusedObject(T obj)
{
//since we dont know if T is a class or a struct test against empty type
T defaultT = T.GetConstructor(T.EmptyTypes).Invoke(null);
if(obj != defaultT)
{
//code
}
}
And for the same exact reason, this does not work either. I was hoping that someone might suggest a method that will work.
That is not a generic function. Unless the function is a member of generic class with a type argument named 'T', you need to declare it like this:
public virtual void SetFocusedObject<T>(T obj)
This will allow you to use default(T) successfully:
public virtual void SetFocusedObject<T>(T obj)
{
if (obj.Equals(default(T))) return;
//code
}
If by empty referece object you mean null and when you compare struct with null you get false, why not use this as test:
public static void Test<T>(T obj)
{
if (obj == null) // default refernce type (which is null)
{
Console.WriteLine("default!");
}
else if(obj.Equals(default(T))) // default value types
{
Console.WriteLine("default!");
}
}
public static void Main()
{
object o = null;
Test(o); // test detects default
Test(0); // test detects default
Class1 c = new Class1();
Test(c); // test does not detect default
}
Though I'm not sure if you consider null default value for reference type, or whether you want to know if default reference type instance is the one created by default constructor.

Extension method restricted to objects containing specific properties

Is there any way to create an extension method whose parameter's only constraint is having specifically-named properties.
e.g.:
public static bool IsMixed<T>(this T obj) where T:?
{
return obj.IsThis && obj.IsThat;
}
I tried to declare the obj as dynamic but it's not allowed.
This feature is often called "duck typing". (Because when you call foo.Quack() all you care about is that it quacks like a duck.) Non-dynamic duck typing is not a feature of C#, sorry!
If you really have no type information about the argument, you can use dynamic in C# 4:
public static bool IsAllThat(this object x)
{
dynamic d = x;
return d.IsThis || d.IsThat;
}
But it would be better to come up with some interface or some such thing that describes the types at compile time.
you would have to get T to implement an interface, then use that in the constraint.
While you cannot do what you're looking to with generic constraints, you could use reflection to check the type at runtime to determine whether it has those properties and dynamically get their values.
Disclaimer: I'm doing this off the top of my head, I may be slightly off in the implementation.
public static bool IsMixed(this object obj)
{
Type type = obj.GetType();
PropertyInfo isThisProperty = type.GetProperty("IsThis", typeof(bool));
PropertyInfo isThatProperty = type.GetProperty("IsThat", typeof(bool));
if (isThisProperty != null && isThatProperty != null)
{
bool isThis = isThisProperty.GetValue(this, null);
bool isThat = isThatProperty.GetValue(this, null);
return isThis && isThat;
}
else
{
throw new ArgumentException(
"Object must have properties IsThis and IsThat.",
"obj"
);
}
}
pretty much the only way to do this is to have an interface as the base of the class you are tring to operate on:
interface iMyInterface
{
}
public static bool IsMixed<T>(this T obj) where T: iMyInterface
{
return obj.IsThis && obj.IsThat;
}

Categories

Resources