How would an IComparer that needs an argument be implemented (might not be relevant but I'm using it on Linq query)?
I suppose it should be called like this:
ListOfObjectsToSort.orderBy(x => x, myCustomComparer(argument));
And this is what i found on how to implement the IComparer but i can't figure out how to change it to pass the argument here:
public class MyComparer : IComparer<object>
{
public int Compare(object x, object y)
{
// code will then return 1,-1 or 0
You can't add an argument to the Compare method or you violate the interface contract. Add a property to the class that can be used in the method:
public class MyComparer : IComparer<object>
{
public int MyArgument {get; set;}
public int Compare(object x, object y)
{
// code will then return 1,-1 or 0
// use MyArgument within the method
}
You can set it in the constructor:
public MyComparer(int argument)
{
MyArgument = argument;
}
Then your syntax would be:
var myCustomComparer = new MyComparer(argument);
ListOfObjectsToSort.orderBy(x => x, myCustomComparer);
or just
ListOfObjectsToSort.orderBy(x => x, new MyComparer(argument));
the problem is that this cannot be done exactly as you're asking.
The reason for this is that you're trying to change the signature of the Compare method, which would result in outside libraries (like Linq!) being unable to call the method, because the arguments they pass are no longer the arguments needed. Thus, the compiler simply does not allow this.
However, there is a way around this, for this particular case, in that since IComparers are used as objects, you could create a class which implements IComparer and takes a custom object in the constructor, saving it to a field and using that for comparison calculations. Thus, you end up with
var comp = new CustomComparer(argument);
ListOfObjectsToSort.OrderBy(x => x, comp);
Related
I have about 1000 classes in which i need to count the number of properties of. I have the following code:
public static int NumberOfProperties()
{
Type type = typeof(C507);
return type.GetProperties().Count();
}
I could copy and paste this in to each class changing the typeof parameter but this seems a bit tedious.
Is there anyway to make an extensions method to do this by just doing var nop = C507.NumberOfProperties();?
Just to add to the answers suggesting an extension for object for completeness: you can also consider implementing an extension only for Type:
public static int GetPropertyCount(this Type t)
{
return t.GetProperties().Length;
}
and use it like this:
typeof(C507).GetPropertyCount();
The advantage is that you can get the number of properties directly from the type and do not have to create an instance first.
So you can write an extension method that uses object or one that uses type.
public static class ObjectExtensions
{
public static int GetNumberOfProperties(this object value)
{
return value.GetType().GetProperties().Count();
}
public static int GetNumberOfProperties(this Type value)
{
return value.GetProperties().Count();
}
}
Usage:
new C507().GetNumberOfProperties();
typeof(C507).GetNumberOfProperties();
However, you explicitly state two things:
I could copy and paste this in to each class changing the typeof
I have about 1000 classes
You'll likely not want to instantiate a 1000 classes or copy and paste typeof() 1000 times
In this case, you will want to read them all from the Assembly.
So something like:
typeof(SomeClass).Assembly.GetTypes().Select(x => new
{
x.Name,
PropertyCount = x.GetType().GetProperties().Count()
});
Where SomeClass is a class (doesn't matter which) where all the classes reside.
I just simply select them out into an anonymous object which contains the Types name and property count.
This:
typeof(SomeClass).Assembly
Is just a convience way to get the assembly. There are other ways.
Assembly.GetAssembly(typeof(Program)).GetTypes()
Assembly.GetCallingAssembly().GetTypes()
Assembly.Load("Some Assemble Ref").GetTypes()
You can do allsorts with the types that you find. If you select out the Type itself, you can instantiate it later using Activator.CreateInstance (if it has parameterless constuctor). You can also auto fill the properties with reflection as well.
It is impossible to have a static extension method as you imagine it. That being said, it would be possible to create a generic method in a helper class as follows.
public static int NumberOfProperties<T>()
{
Type type = typeof(T);
return type.GetProperties().Count();
}
Given a type SomeType it could be called as int n = NumberOfProperties<SomeType>().
You could make an extension method on object like this:
public static int PropertyCount(this object thing)
{
return thing.GetType().GetProperties().Count();
}
And use it on any object you like:
var x = "some string";
var numProps = x.PropertyCount();
If you want to have an extension method on object:
public static ObjectExtensions
{
public static int NumberOfProperties(this object value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetType().GetProperties().Length;
}
}
...
C507 myObj = new C507();
// How many properties does myObj instance have?
int propCount = myObj.NumberOfProperties();
If you want to have an extesnion method on Type:
public static TypeExtensions
{
public static int NumberOfProperties(this Type value)
{
if (null == value)
throw new ArgumentNullException("value"); // or return 0
// Length: no need in Linq here
return value.GetProperties().Length;
}
}
...
// How many properties does C507 type have?
int propCount = typeof(C507).NumberOfProperties();
There are a couple of ways to do this that are variations of the same thing.
You can pass the Type as an argument to a method:
public static class Helper {
public static int NumberOfProperties(Type type)
{
return type.GetProperties().Count();
}
}
Which you would call like this:
// Imagine you have a class called MyClass
var result = Helper.NumberOfProperties(typeof(MyClass));
You use use the generic system in C# to make the syntax a little cleaner. That would look like this:
public static class Helper {
// Notice the argument was removed and
// the use of the "generic" syntax <T>
public static int NumberOfProperties<T>()
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
And you would call it like this:
var result = Helper.NumberOfProperties<MyClass>();
You could also use "Extensions" which allow you to call it as if it was a method that belonged to your classes.
public static class Helper {
// notice the `this` keyword before the parameter
// this is what tells C# that this is an extension method
public static int NumberOfProperties<T>(this T #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
This will allow you to call the method like this:
var instance = new MyClass();
var result = instance.NumberOfProperties();
In this example I used the generic syntax so that it applies to any type of object. If you wanted to limit it to only objects that inherit from a specific interface or base class you would just change it from using the generic syntax to using the base class/interface. Like this:
public static class Helper {
// notice the type got changed from a generic <T>
// to specifying the exact class you want to "extend"
public static int NumberOfProperties(this MyBaseClass #this)
{
var type = typeof(T);
return type.GetProperties().Count();
}
}
As #rené-vogt mentioned you can also create the extension method so that it extends the type Type instead. See his answer in this thread: https://stackoverflow.com/a/38455233/984780
You can make a generic extension method which can apply to all types:
public static int PropertyCount<T>(this T obj)
{
return typeof(T).GetProperties().Length;
}
This will apply to all types including value types (I.E. structs) which applying to object will not. Thanks to piedar for pointing out my mistake here, applying to object does still add this extension method to value types.
If your classed can implement an interface, then you can extend that interface.
public interface IExtensible {
}
class C507 : IExtensible {
}
public static int NumberOfProperties(this IExtensible extensible)
{
Type type = extensible.GetType();
return type.GetProperties().Count();
}
That being said, having hundreds of (generated?) classes looks like a bad solution to begin with.
I have a List<Points>() and I want to sort it with a custom comparer function.
I made:
public int MyCompare(Point p1, Point p2)
{
...
}
// In my main
// ...
points_.Sort(MyCompare);
// ...
I works, all right.
Now I want to sort everything but the first element, so I thought to do:
points_.Sort(1, points_.Count()-1, MyCompare);
But with this overload he wants as argument an IComparer.
How can I solve this?
Note that Point is not a custom class, it is from Xna framework. I don't want to implement a custom class with : IComparer
If you do not want to implement IComparer, you could create one from a delegate using the Comparer<T>.Create static method, like this:
points_.Sort(1, points_.Count()-1, Comparer.Create(MyCompare));
or even
points_.Sort(1, points_.Count()-1, Comparer.Create((a, b) => {
... // comparison logic goes here
}));
As pointed out by #dasblinkenlight with .NET 4.5+ there's an ad-hoc method to convert a Comparison<T> delegate to an IComparer<T>.
But if you're stuck with a lower version, you can use this class to convert a Comparison<T> delegate to IComparer<T>:
public class DelegateComparer<T> : IComparer<T>
{
private readonly Comparison<T> compDelegate;
public DelegateComparer(Comparison<T> compDelegate)
{
if (compDelegate == null)
throw new ArgumentNullException("compDelegate");
this.compDelegate = compDelegate;
}
public int Compare(T x, T y)
{
return compDelegate(x, y);
}
}
Usage example:
points_.Sort(1, points_.Count()-1, new DelegateComparer<Point>(MyCompare));
I have a function I'd like to write where return a sorted list. I want to pass in a custom comparison for the objects. The examples below are rather oversimplified, but if I can get past this, I should be set.
I've tried declaring a delegate of the right type (I think):
public delegate int ObjectSorter(MyObject x, MyObject y);
Calling it with the right syntax:
GetList(delegate(MyObject a, MyObject b) { return a.CompareTo(b); });
But when I pass that to the list, I get that there are argument problems:
public List<MyObject> GetList(ObjectSorter os)
{
List<MyObject> objectList = FillTheList();
objectList.Sort(os); // Invalid
return ObjectList;
}
So trying a different approach:
GetList((x, y) => { return x.CompareTo(y); });
public List<MyObject> GetList(Func<MyObject, MyObject, int> sorter)
{
List<MyObject> objectList = FillTheList();
objectList.Sort(sorter); // Invalid also
// This syntax DOES work, but too specific. And why does it work?
nl.Sort((x, y) => x.CompareTo(y));
return ObjectList;
}
Doesn't work either.
I'm trying to make this as easy as possible for the caller to get a custom comparison into the function, and for the function to know as little as possible about the workings of the sort itself. I'd rather not have the caller go through all of the trouble of creating an class derived from IComparer and passing that in.
Should be:
objectList.Sort(new Comparison<MyObject>(sorter));
Or just change your method signature to:
public List<MyObject> GetList(Comparison<MyObject> sorter)
Comparison<MyObject> is equivalent to your Func<MyObject, MyObject, int> sorter.
nl.Sort((x, y) => x.CompareTo(y)); works because the compiler automatically turns (x, y) => x.CompareTo(y) into a Comparison<MyObject> delegate. When you have the code (x, y) => x.CompareTo(y), the compiler uses the context to determine its type.
Once it's stored as a specific delegate type (e.g. Func<MyObject, MyObject, int> or Comparison<MyObject>), that is its type, and it will not implicitly be converted to another. However, it can be explicitly converted to another type if it is compatible, as in new Comparison<MyObject>(sorter).
You can pass in a function using Func for example:
private void Foo(Func<MyObject, MyObject, int> sortMethod)
{
list.Sort(new Comparison<MyObject>(sortMethod));
}
Example sort method:
public static int SortBytName(MyObject x, MyObject y)
{
return x.Name.CompareTo(y.Name);
}
Is there a way of passing in a method to a function as a parameter and then calling it via list.Sort()? I've tried this:
public static string BuildHumanSitemap(Func<TreeNode, TreeNode, int> sortMethod, params string[] classNames)
{
//calling list sort on method passed as parameter
nodes.sort(sortMethod);
}
Where the functions i want to pass in all take the same params e.g.
private static int SortByDateCreated(TreeNode x, TreeNode y)
{
DateTime xT = (DateTime)x["DocumentCreatedWhen"];
DateTime yT = (DateTime)y["DocumentCreatedWhen"];
return xT.CompareTo(yT);
}
I've also tried using an Action delegate type but the sort method complains when i pass it as a parameter. Can anyone offer a suggestion on how to do this?
Thankyou
Create new Comparison delegate and pass it to Sort method:
nodes.Sort(new Comparison<TreeNode>(sortMethod));
Maybe instead of taking in a Func<,,> delegate, you should consume a Comparison<> delegate. Because that's what List<> wants (for historical reasons; the List<>.Sort method was written for .NET 2.0, before the Func delegates were introduced).
Therefore:
public static string BuildHumanSitemap(Comparison<TreeNode> sortMethod, params string[] classNames)
{
//calling list sort on method passed as parameter
nodes.Sort(sortMethod);
}
Then call your method very simply like this:
BuildHumanSitemap(SortByDateCreated);
where SortByDateCreated is the "method group" from your question.
There's no need for first creating a delegate instance of type Func<TreeNode, TreeNode, int> and then create another delegate instance (of type Comparison<TreeNode>) which references the first one.
Of course you can also call your BuildHumanSitemap method with a lambda arrow as the first argument.
It works this way:
TreeView.TreeViewNodeSorter = new CustomNodeSorter();
private class CustomNodeSorter : IComparer
{
public int Compare(object x, object y)
{
DateTime xT = (DateTime)x["DocumentCreatedWhen"];
DateTime yT = (DateTime)y["DocumentCreatedWhen"];
return xT.CompareTo(yT);
}
}
Solution with IComparer<T>.
Comparer
public class MyTreeNodeComparer : IComparer<TreeNode>
{
public int Compare(TreeNode x, TreeNode y)
{
DateTime xT = (DateTime)x["DocumentCreatedWhen"];
DateTime yT = (DateTime)y["DocumentCreatedWhen"];
return xT.CompareTo(yT);
}
}
Usage
list.Sort(new MyTreeNodeComparer());
I tries some Unit Testing and ran into a problem of testing methods which use classes instances and not the interfaces. In that case I found that MS Moles can help me. But the it seems that they are not friendly with type casting situations. And I found no info and even no questions how to deal with this situation. Example:
public class ClassA
{
public int Number {get {return 10;}}
}
public class ClassB
{
public int Count1(ClassA arg) { return arg.Number; }
public int Count2(object arg) { return (arg as ClassA).Number; }
}
and while testing
var cl = new MolesUnitTesting.Moles.MClassA();
MolesUnitTesting.Moles.MClassA.AllInstances.NumberGet = t1 => 20;
The first Count works just fine and returns 20 but casting in the second returns Null. Is there any way to test such method without using interface and usual mocking? If there is other lib that can help me please provide me with it's name.
Instead of mocking all instances of the ClassA type you can do the following:
var target = new MClassA();
target.NumberGet = () => 42;
Assert.AreEqual(Count1(target), 42);
Assert.AreEqual(Count2(target.Instance), 42);
Notice that for the Count1 you can use the mole directly because it will be automatically converted to a ClassA instance. However, since Count2 receives an object you need to be explicit and passed the target.Instance which represents the moled ClassA instance.
The reason Count1(target) works is because the generated mole class MClassA, which inherits from MoleBase<ClassA>, defines the following implicit operator:
public static implicit operator ClassA(MoleBase<ClassA> mole) { // ... }