Microsoft.VisualStudio.TestTools.UnitTesting.Assert generic method overloads behavior - c#

In the Microsoft.VisualStudio.TestTools.UnitTesting namespace, there is the handy static class Assert to handle the assertions going on in your tests.
Something that has got me bugged is that most methods are extremely overloaded, and on top of that, they have a generic version. One specific example is Assert.AreEqual which has 18 overloads, among them:
Assert.AreEqual<T>(T t1, T t2)
What is the use of this generic method? Originally, I thought this was a way to directly call the IEquatable<T> Equals(T t) method, but that is not the case; it will always call the non-generic version object.Equals(object other). I found out the hard way after coding quite a few unit tests expecting that behavior (instead of examining the Assert class definition beforehand like I should have).
In order to call the generic version of Equals, the generic method would had to be defined as:
Assert.AreEqual<T>(T t1, T t2) where T: IEquatable<T>
Is there a good reason why it wasn't done this way?
Yes, you loose the generic method for all those types that don't implement IEquatable<T>, but it's not a great loss anyway as equality would be checked through object.Equals(object other), so Assert.AreEqual(object o1, object o2) is already good enough.
Does the current generic method offer advantages I'm not considering, or is it just the case that no one stopped to think about it as it's not that much of a deal? The only advantage I see is argument type safety, but that seems kind of poor.
Edit: fixed an error where I kept referring to IComparable when I meant IEquatable.

The method having that constraint would be non-ideal because of the oft-faced problem of constraints not being part of the signature.
The issue would be that for any T that is not covered by its own specific overload, the compiler would choose the generic AreEqual<T> method as the best fit during overload resolution, as it would indeed by an exact match. In a different step of the process, the compiler would evaluate that T passes the constraint. For any T that does not implement IEquatable<T>, this check would fail and the code would not compile.
Consider this simplified example of the unit testing library code and a class that might exist in your library:
public static class Assert
{
public static void AreEqual(object expected, object actual) { }
public static void AreEqual<T>(T expected, T actual) where T : IEquatable<T> { }
}
class Bar { }
Class Bar does not implement the interface in the constraint. If we were then to add the following code to a unit test
Assert.AreEqual(new Bar(), new Bar());
The code would fail to compile because of the unsatisfied constraint on the method that is the best candidate. (Bar substitutes for T, which makes it a better candidate than object.)
The type 'Bar' cannot be used as type parameter 'T' in the generic type or method 'Assert.AreEqual<T>(T, T)'. There is no implicit reference conversion from 'Bar' to 'System.IEquatable<Bar>'.
In order to satisfy the compiler and allow our unit test code to compile and run, we would have to cast at least one input to the method to object so that the non-generic overload can be chosen, and this would be true for any given T that might exist in your own code or code you consume that you wish to use in your test cases that does not implement the interface.
Assert.AreEqual((object)new Bar(), new Bar());
So the question must be asked -- would that be ideal? If you were writing a unit testing library, would you create such a method with such an unfriendly limitation? I suspect you would not, and the implementers of the Microsoft unit testing library (whether it was for this reason or not) did not either.

Basically, the generic overload force you to compare two objects of same type. In case you change type of expecting or actual value, the compilation error will appear. Here is MSDN blog describing it quite well.

You can decompile the method and see that all it really does is add a type check (via ILSpy), which isn't even done correctly in my opinion (it checks types after equality):
public static void AreEqual<T>(T expected, T actual, string message, params object[] parameters)
{
message = Assert.CreateCompleteMessage(message, parameters);
if (!object.Equals(expected, actual))
{
string message2;
if (actual != null && expected != null && !actual.GetType().Equals(expected.GetType()))
{
message2 = FrameworkMessages.AreEqualDifferentTypesFailMsg((message == null) ? string.Empty : Assert.ReplaceNulls(message), Assert.ReplaceNulls(expected), expected.GetType().FullName, Assert.ReplaceNulls(actual), actual.GetType().FullName);
}
else
{
message2 = FrameworkMessages.AreEqualFailMsg((message == null) ? string.Empty : Assert.ReplaceNulls(message), Assert.ReplaceNulls(expected), Assert.ReplaceNulls(actual));
}
Assert.HandleFailure("Assert.AreEqual", message2);
}
}
Theoretically, it could use EqualityComparer<T>.Default to use the generic Equals, if available, but which would fallback to non-generic Equals otherwise. This would then not require a constraint to IEquatable<T>. Having a different behavior for the generic and non-generic Equals methods are a code smell, IMO.
Honestly, the generic overload is not tremendously useful unless you type out the generic parameter. I cannot count how many times I've mistyped a property or compared two properties that are different types and it picked the AreEqual(object,object) overload. Thus giving me a failure much later at run time rather than compile time.

Related

Constraint where 2 generic types of a class must not be the same [duplicate]

Is it possible to implement a class constrained to two unique generic parameters?
If it is not, is that because it is unimplemented or because it would be impossible given the language structure (inheritance)?
I would like something of the form:
class BidirectionalMap<T1,T2> where T1 != T2
{
...
}
I am implementing a Bidirectional dictionary. This is mostly a question of curiosity, not of need.
Paraphrased from the comments:
Dan: "What are the negative consequence if this constraint is not met?"
Me: "Then the user could index with map[t1] and map[t2]. If they were the same type, there would be no distinction and it wouldn't make any sense."
Dan: The compiler actually allows [two generic type parameters to define distinct method overloads], so I'm curious; does it arbitrarily pick one of the methods to call?
Expanding on the example to highlight the problem:
public class BidirectionalMap<T1,T2>
{
public void Remove(T1 item) {}
public void Remove(T2 item) {}
public static void Test()
{
//This line compiles
var possiblyBad = new BidirectionalMap<string, string>();
//This causes the compiler to fail with an ambiguous invocation
possiblyBad.Remove("Something");
}
}
So the answer is that, even though you can't specify the constraint T1 != T2, it doesn't matter, because the compiler will fail as soon as you try to do something that would violate the implicit constraint. It still catches the failure at compile time, so you can use these overloads with impunity. It's a bit odd, as you can create an instance of the map (and could even write IL code that manipulates the map appropriately), but the C# compiler won't let you wreak havoc by arbitrarily resolving ambiguous overloads.
One side note is that this kind of overloading could cause some odd behaviors if you're not careful. If you have a BidirectionalMap<Animal, Cat> and Cat : Animal, consider what will happen with this code:
Animal animal = new Cat();
map.Remove(animal);
This will call the overload that takes Animal, so it will try to remove a key, even though you might have intended to remove the value Cat. This is a somewhat artificial case, but it's enough to warrant caution when very different behaviors occur as a result of method overloading. In such cases, it's probably easier to read and maintain if you just give the methods different names, reflecting their different behaviors (RemoveKey and RemoveValue, let's say.)
The inequality wouldn't help the compiler to catch errors. When you specify constraints on type parameters, you are telling the compiler that variables of this type will always support a certain interface or will behave in certain ways. Each of those allows the compiler to validate something more like "this method will be present so it can be called on T".
The inequality of type parameters would be more like validating that method arguments are not null. It is part of the logic of the program, not its type safety.
Type constraints seem like a misnomer. While they do contrain what the type parameter is, the purpose is to let the compiler know what operations are available to the type.
If you wanted to, you can have a constraint where T1 and T2 both derive from seperate concrete base classes, but I don't think that's quite what you want.
I'm not entirely sure why this would be a desirable compile time check. It would be possible to essentially by-pass the condition by boxing either the key or the value, thereby rendering the compile-time check useless.
Some consideration needs to be made to determine... what errors am I trying to prevent?
If you are simply stopping a lazy co-worker from not reading the documentation, then add a Debug only check and throw an exception. This way the check can be removed for release code e.g.
#if Debug
if (T1 is T2 || T2 is T1)
{
throw new ArguementException(...);
}
#endif
If you are attempting to prevent a malevolent person from using your library in an unintended way, then perhaps a runtime check is needed, otherwise it would be easy to box the key or value.
No, you cannot use equality (or inequality) as a constraint. Simply put, equality is not a constraint, but a condition. You should test for a condition such as equality or inequality of types in the constructor and throw an appropriate exception.
There is no effective way to do this without imposing any other restrictions on the types themselves. As someone else noted, you could make constraints that the two types derived from two different base classes, but that's probably not very good from a design standpoint.
Edited to add: the reason this is not implemented is most likely because nobody at Microsoft ever considered something like this to be necessary to enforce at compile time, unlike the other constraints which have to do with how you're actually able to use variables of the specified types. And as some commenters have pointed out, you can certainly enforce this at runtime.

Using generic constraints with value types

I am experimenting with fluent extension methods.
I have the following simple extension method to perform a safe cast.
public static T As<T>(this Object source)
where T : class
{
return source as T;
}
This worked well, but when I tried to make it intuitive to use valuetypes with an overload
public static T As<T>(this ValueType source)
where T : struct
{
return (T)source;
}
I ran into problems. The method resolution logic always chooses the first method above, and gives a syntax error (accurately) that the struct is not a class.
Is there a way to handle the above, or should I go the route of removing the constraint while testing for and handling all types in the same method?
==== Edit: to answer questions ====
I am compiling this against the 3.5 framework. I'm not really trying to accomplish anything in particular; this is just an experiment with the above. My interest was piqued and I threw together some code.
I'm not particularly concerned with it remaining a 'safe' cast. That is how it started, and can be kept safe with default() -- but that's not really the focus of the question and code to ensure 'safeness' would just obscure.
As to the expressiveness, no value.As<int>() is not any more expressive than (int)value; but why should the user of the method have to 'just know' it only works with reference types? My trying to work it in was more about the expected behavior of the method than expressive writing.
The code snippet value.As<DateTime>(), gives the error "The type 'System.DateTime' must be a reference type in order to use it as parameter 'T' in the generic type or method ....As(object)". From the error message I see it is resolving to use the top method above as it is the one requiring the reference type.
In .NET 4, the second overload is chosen based on your code sample. (Also just tested against .NET 3.5, same result.)
int myInt = 1;
long myLong = myInt.As<long>(); // chooses ValueType version
However, this only gets us to the scene of the next crash. The (T)source; results in an invalid cast exception. You could get around that by writing the method as
public static T As<T>(this ValueType source)
where T : struct
{
return (T)Convert.ChangeType(source, typeof(T));
}
However, I wonder what you're actually looking to achieve, as I do not see the immediate benefit. (And for that matter, this isn't safe like the source as T object version.) For example, how is
long myLong = myInt.As<long>();
Any more expressive or easier to use than
long myLong = (long)myInt;

What is the difference between these two Unit Test Assertions?

Came across the following MS Unit Test:
[TestMethod]
public void PersonRepository_AddressCountForSinglePerson_IsNotEqualToZero()
{
// Arrange.
Person person;
// Act.
person = personRepository.FindSingle(1);
// Assert.
Assert.AreNotEqual<int>(person.Addresses.Count, 0);
}
I have never seen the use of generics when doing Assertions.
This is how i would write the Assertion:
// Assert.
Assert.AreNotEqual(person.Addresses.Count, 0);
What is the difference?
When i hover over the AreNotEqual() overload i am using, the method is using the overload which compares two doubles (not sure why there isn't an int, int overload).
And if i do put the generic type-parameter of <int> in, ReSharper says it's redundant.
So my question is: if the way i do it is still type-safe, why use generic assertions?
So my question is - if the way i do it is still type-safe, why use generic assertions?
You are using the generic assertion now. The compiler sees the generic method, and chooses it at compile time. This is why Resharper is saying that the <int> is redundant - it's not because the method is redundant, but rather that the compiler can implicitly determine that the Assert.AreNotEqual<int> method is the proper method to use.
In general, you often don't need to specify the type on generics. This is what makes LINQ syntax bearable - without it, you'd need to specify the types on every method call in the chain, and anonymous types would be unusable.
That being said, there are times where specifying the generic type is required. This is mainly if the compiler cannot determine the type automatically, such as if there is no matching parameter in the argument list (ie: Foo.Create<MyClass>()), or if the type can't be determined for some other reason.

How to do a static cast in C#?

Given a couple types like this:
interface I {}
class C : I {}
How can I do a static type cast? By this I mean: how can I change its type in a way that gets checked at compile time?
In C++ you can do static_cast<I*>(c). In C# the best I can do is create a temporary variable of the alternate type and try to assign it:
var c = new C();
I i = c; // statically checked
But this prevents fluent programming. I have to create a new variable just to do the type check. So I've settled on something like this:
class C : I
{
public I I { get { return this; } }
}
Now I can statically convert C to I by just calling c.I.
Is there a better way to do this in C#?
(In case anyone's wondering why I want to do this, it's because I use explicit interface implementations, and calling one of those from within another member function requires a cast to the interface type first, otherwise the compiler can't find the method.)
UPDATE
Another option I came up with is an object extension:
public static class ObjectExtensions
{
[DebuggerStepThrough]
public static T StaticTo<T>(this T o)
{
return o;
}
}
So ((I)c).Doit() could also be c.StaticTo<I>().Doit(). Hmm...probably will still stick with the simple cast. Figured I'd post this other option anyway.
Simply cast it:
(I)c
Edit Example:
var c = new C();
((I)c).MethodOnI();
Write an extension method that uses the trick you mentioned in your UPDATE:
public static class ObjectExtensions
{
public static T StaticCast<T>(this T o) => o;
}
To use:
things.StaticCast<IEnumerable>().GetEnumerator();
If things is, e.g., IEnumerable<object>, this compiles. If things is object, it fails.
// Compiles (because IEnumerable<char> is known at compiletime
// to be IEnumerable too).
"adsf".StaticCast<IEnumerable>().GetEnumerator();
// error CS1929: 'object' does not contain a definition for 'StaticCast'
// and the best extension method overload
// 'ObjectExtensions.StaticCast<IEnumerable>(IEnumerable)'
// requires a receiver of type 'IEnumerable'
new object().StaticCast<IEnumerable>().GetEnumerator();
Why Use a Static Cast?
One common practice during refactoring is to go ahead and make your changes and then verify that your changes have not caused any regressions. You can detect regressions in various ways and at various stages. For example, some types of refactoring may result in API changes/breakage and require refactoring other parts of the codebase.
If one part of your code expects to receive a type (ClassA) that should be known at compiletime to implement an interface (IInterfaceA) and that code wants to access interface members directly, it may have to cast down to the interface type to, e.g., access explicitly implemented interface members. If, after refactoring, ClassA no longer implements IIterfaceA, you get different types of errors depending on how you casted down to the interface:
C-style cast: ((IInterfaceA)MethodReturningClassA()).Act(); would suddenly become a runtime cast and throw a runtime error.
Assigning to an explicitly-typed variable: IInterfaceA a = MethodReturningClassA(); a.Act(); would raise a compiletime error.
Using the static_cast<T>-like extension method: MethodReturningClassA().StaticCast<IInterfaceA>().Act(); would raise a compiletime error.
If you expected your cast to be a downcast and to be verifiable at compiletime, then you should use a casting method that forces compiletime verification. This makes the intentions of the code’s original developer to write typesafe code clear. And writing typesafe code has the benefit of being more verifiable at compiletime. By doing a little bit of work to clarify your intention to opt into typesafety to both other developers, yourself, and the compiler, you magically get the compiler’s help in verifying your code and can catch repercussions of refactoring earlier (at compiletime) than later (such as a runtime crash if your code didn’t happen to have full test coverage).
var c = new C();
I i = c; // statically checked
equals to
I i = new C();
If you're really just looking for a way to see if an object implements a specific type, you should use as.
I i = whatever as i;
if (i == null) // It wasn't
Otherwise, you just cast it. (There aren't really multiple types of casting in .NET like there are in C++ -- unless you get deeper than most people need to, but then it's more about WeakReference and such things.)
I i = (I)c;
If you're just looking for a convenient way to turn anything implementing I into an I, then you could use an extension method or something similar.
public static I ToI(this I #this)
{
return #this;
}

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