Home > OS >  A little help to understanding a C# exercise with Interface with Generics
A little help to understanding a C# exercise with Interface with Generics

Time:06-07

I'm doing an exercise in which I have some trouble understanding how to begin with. The exercise is this one:


Given the Interface

public interface I<T> { T P {get;} }

Write the extension-method "Indexing" that, given an array "s" of elements of type "I< T >", where "T" is a parameter instantiable only with an enumeration type, it produce a dictionary that associates each value "v" of "T" type with the subsequence "s" of the "s" elements at the time of the call of the method, that have "v" as the value of "P" property.

For example, by using *enum Day { Mo, Tu, We, Th, Fr } *, if "arr" is the array [e0, e1, e2, e3, e4, e5] where:

e0 - ... P == Day.Mo ...
e1 - ... P == Day.Mo ...
e2 - ... P == Day.We ...
e3 - ... P == Day.Mo ...
e4 - ... P == Day.Fr ...
e5 - ... P == Day.We ...

You will get:

    var  res = arr.Indexing ();
for (int i = 1; i < arr.Length;   i) arr[i] = arr [0];

// even  changing  arr is  still  true  that
// res[Day.Mo] == [e0 , e1 , e3]
// res[Day.Tu] empty  array
// res[Day.We] = [e2 , e5]
// res[Day.Th] empty  array
// res[Day.Fr] = [e4]

I don't want a full solved exercise, but I need a hint to start working with. I think I'm missing something about the implementation of I< T > (which is the first time I see something like this). In particular, I have doubts regarding how to create the Extension Method and how to test the given example.

Thanks in advance.

CodePudding user response:

Extension method

An extension method is just a convenient way of calling a static method, which does mainly operations on a specific type. E.g. the following method Print can be written in two ways.

public static void Print(string str)
{
    Console.WriteLine(str);
}

public static void Print(this string str)
{
    Console.WriteLine(str);
}

The first one is called as you would expect. Print("Hello World!");

The second one (extension method) can be called directly on a string. "Hello World!".Print();

An extension method defines with its first "this" parameter on which type it is callable. It is important to know, that you can only use public properties and methods of the type inside an extension method. The same as in a usual static method.

Generics

You have never seen a generic class before, or just no generic interface? In case of the latter: It is basically the same and requires you to specify the specific type of the interface on usage. In your case, you can specify the type of the property P. The example the exercise shows specified it as the enum Day. If you have never seen or used generics, you should first have a look at the documentation and tutorials.

With that being said, your extension method should have a signature like this.

public static void Indexing<T>(this IEnumerable<I<T>> s) where T : Enum
{
    ...
}

I am not sure why the exercise wants you to use an Array, because Arrays cannot be Generics in C#. I used an IEnumerable in my signature instead. The where statement restricts the possible types of T to Enums.

Testing

I suggest you have a look at unit testing to test your implementation. Once you sat it up and get the hang of it, it is very helpful. I would recommend xUnit. NUnit is fine too. I would not recommend Microsoft.VisualStudio.UnitTesting for .net-core and above.

I hope this helps and is not too much of an unwanted solution :)

CodePudding user response:

I hope you are familiar with the basics of Interfaces or Generic Types in C# already! If not, I can recommend checking out the following ressources:

Now you have those two concepts mixed together. Based on your example with the day-enum, a class IDay that implements the interface I<T> could look like this for example:

    public enum Day { Mo, Tu, We, Th, Fr }

    public class IDay : I<Day>
    {
        public Day P { get; }

        public IDay(Day day)
        {
            P = day;
        } 
    }

Now, an extension method is a method that acts like it is provided by the class of the object itself, but is actually just an addendum from another static class, to add more functionality to this first class. It the this keyword in the parameters to mark which class it should extend. So the general structure would always look like this:

public static class ClassForYourExtensions
{
    public static ReturnType ExtensionMethod(this ClassYouWantToExtend obj)
    {
        // Write code like you are used to in here
    }
}

With the info you provided, we know your extension method should satisfy the following conditions:

  • It returns an object of type Dictionary<T, I<T>[]>
  • It should extend / take in an object of type I<T>[]
  • The generic Type T has the be an enum type for this method

This means we can write the extension function the following way:

    public static Dictionary<T, I<T>[]> Indexing<T>(this I<T>[] arr) where T : Enum

Another tip from me: You can use the Enum.GetValues() Function to iterate through all the values of the enum T. So, without spoilering too much, I would start the function like this:

    public static Dictionary<T, I<T>[]> Indexing<T>(this I<T>[] arr) where T : Enum
    {
        Dictionary<T, I<T>[]> result = new();

        foreach(var element in Enum.GetValues(typeof(T)))
        {
            // Add values to the result here...
        }

        return result;
    }

Regarding your last question, the testing, you first need to instantiate an array of your class that implements the interface (in this case I called it IDay, as in the example above) and then you can simply call the Indexing extension function from this element:

    public static void Testing()
    {
        IDay[] days = new IDay[]
        {
            new IDay(Day.Mo),
            new IDay(Day.Tu),
            new IDay(Day.We),
            new IDay(Day.Th),
            new IDay(Day.Fr)
        };

        var res = days.Indexing();
    }

I hope this helps for getting a better feeling for the syntax and the concepts you have to use for your task :)

  • Related