Steffen_dd
Steffen_dd

Reputation: 69

How can I use an method from a collection as an generic method for other classes

I’m locking for a way to use my function GetItem as an generic-Method for some other classes. These classes are based all from CBase and I use the method GetItem into nearly 20 classes. The only thing of difference into the 20 classes are the classtype. In this example is the classtype CLoad.

I would use the Function GetItem as an generic-method, but I doesn’t see a way to do that. At the moment I copy this function to every class.

I hope there is a better way.

using System.Collections.ObjectModel;
using System.Data;
using System.Linq;

namespace WindowsFormsGenerics
{
    public class CLoadListe : Collection<CLoad>
    {
        ///<param name="Searchstring"> String nach dem die Lastenliste durchsucht werden soll </param>
        ///<param name="Parameter"> NAME für Lastenname, ALIASNAME oder DESCRIPTION</param>
        public CLoad GetItem(string Searchstring, string Parameter = "NAME")
        {
            if (this.Count == 0) return null;
            if (Searchstring.Length == 0) return null;
            switch (Parameter)   // Parameter auswerten
            {
                case ("NAME"): return this.Where(item => item.Name == Searchstring).FirstOrDefault();
                case ("DESCRIPTION"): return this.Where(item => item.Description == Searchstring).FirstOrDefault();
                default: throw new System.Exception($"Suchparameter {Parameter} nicht vorhanden");
            }
        }

    }

    /// <summary>Basisklasse für alle Elemente </summary>
    public class CBase
    {
        /// <summary> Elementname </summary>
        public string Name { get; set; }
        /// <summary> Beschreibung </summary>
        public string Description { get; set; }
    }
    public class CKnoten : CBase { }
    public class COneNodeElement : CBase
    {
        /// <summary> KnotenOne des Elementes </summary>
        public CKnoten KnotenOne { get; set; }
        /// <summary> Schaltzustand am KnotenOne </summary>
        public bool SwitchOne { get; set; }
    }
    public class CLoad : COneNodeElement { }


}

Thanks Steffen

Upvotes: 1

Views: 63

Answers (3)

Adriano Repetti
Adriano Repetti

Reputation: 67090

Add a base class for your lists:

public abstract class CListe<T> : Collection<T>
    where T : CBase
{
    public T GetItem(string Searchstring, string Parameter = "NAME")
    {
        // As is...
    }
}

Now LoadListe is just:

public sealed CLoadListe : CListe<CLoad> { }

However I'd highlight few minor issues here:

  • In C# usually classes are not prefixed with C then you should have Liste, Load and so on.
  • Parameters are usually camelCase.
  • You do not need a string parameter, what's for when you have enum?
  • Your classes are all not-abstract and not-sealed. Make classes you don't want to instantiate abstract and classes you do not want to extend through inheritance sealed.
  • Your tests for this.Count == 0 and searchString.Length == 0 are useless, this.Where() will perform as required without them (it may be a an attempt of micro optimization but it will degrade common path performance). You may instead want to add argument checking (for example if searchString is null throw ArgumentNullException).
  • Do not ever throw a generic Exception when you have a better exception type. In this case you may use ArgumentException (or InvalidEnumArgumentException if you switch to an enum).
  • Given that I'd drop parameter Parameter you also are performing an ordinal comparison, not always what you may expect or you may be aware of. If you really have to stick with strings you'd better use String.Equals() with StringComparison.InvariantCultureIgnoreCase.

Upvotes: 2

Dmitriy
Dmitriy

Reputation: 133

You can write an extension method

public static class CLoadExtension
{
    public static CLoad GetItem(this Collection<CLoad> coll, string Searchstring, string Parameter = "NAME")
    {
        if (this.Count == 0) return null;
            if (Searchstring.Length == 0) return null;
            switch (Parameter)   // Parameter auswerten
            {
                case ("NAME"): return this.Where(item => item.Name == Searchstring).FirstOrDefault();
                case ("DESCRIPTION"): return this.Where(item => item.Description == Searchstring).FirstOrDefault();
                default: throw new System.Exception($"Suchparameter {Parameter} nicht vorhanden");
            }
    }
}

Upvotes: -1

Ferhat Sayan
Ferhat Sayan

Reputation: 226

This should work:

public static class CBaseExtensions
{
    ///<param name="Searchstring"> String nach dem die Lastenliste durchsucht werden soll </param>
    ///<param name="Parameter"> NAME für Lastenname, ALIASNAME oder DESCRIPTION</param>
    public static T GetItem<T>(this Collection<T> self, string Searchstring, string Parameter = "NAME") where T : CBase
    {
        if (self.Count == 0) return null;
        if (Searchstring.Length == 0) return null;
        switch (Parameter)   // Parameter auswerten
        {
            case ("NAME"): return self.FirstOrDefault(item => item.Name == Searchstring);
            case ("DESCRIPTION"): return self.FirstOrDefault(item => item.Description == Searchstring);
            default: throw new System.Exception($"Suchparameter {Parameter} nicht vorhanden");
        }
    }
}

You can call it now like this:

var list = new CLoadListe();
var items = list.GetItem("searchstring", "parameter");

Upvotes: 1

Related Questions