0

I'm quite new to generics and I have a problem where two methods essentially do the same. The only difference is the parameter.

I have a json list, with a lot of JSON objects, and I have two methods getting the different objects in two different ways. The object is a language object consisting of an ID and code.

I have tried digging down in generics, since I think this is how I can solve this problem to make the code even nicer. However, I have a really hard time understanding it.

The methods look like this.

public LanguageDto GetLanguageById(int id)
{
    var o = JObject.Parse(json);
    var a = (JArray) o["list"];
    var _list = a.ToObject<IList<LanguageDto>>();

    return _list.FirstOrDefault(x => x.Id == id);
}

public LanguageDto GetLanguageByCode(string code)
{
    var o = JObject.Parse(json);
    var a = (JArray) o["list"];
    var _list = a.ToObject<IList<LanguageDto>>();

    return _list.FirstOrDefault(x => x.LanguageCode == code);
}

What I would like is a combined method that looks like this

public LanguageDto GetLanguage(T)
{
    var o = JObject.Parse(json);
    var a = (JArray) o["list"];
    var _list = a.ToObject<IList<LanguageDto>>();

    return _list.FirstOrDefault(x => x.T == T);
}

I hope you get my pseudo code.

If someone has some great learning resources on Generics or something that touches this problem, I would appreciate if you would share.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • What you are trying to do is pass the property name into the method and use it to select from your Json List, is that correct? Perhaps this will help you (https://stackoverflow.com/questions/1196991/get-property-value-from-string-using-reflection-in-c-sharp) – Ryan Wilson May 20 '19 at 19:40
  • That is correct :-) – Julian Kock May 20 '19 at 19:42
  • 2
    I recommend you keep it just the way it is. It "ain't broke", as they say. Furthermore, this is not what generics are for. What you're trying to do will be harder to read, harder to use, harder to maintain, and slower at runtime. Speaking of which, do you really need to parse that JSON every time anybody looks up a value from it? – 15ee8f99-57ff-4f92-890c-b56153 May 20 '19 at 19:44
  • Hey Ed. Thanks for your information. I can see your point. How come it be slower at runtime? Regarding to your question, are you suggesting I put the parsed json into a property? I really appreciate your help! – Julian Kock May 20 '19 at 19:50
  • Instead of supplying an 'id' or 'code', maybe supply the lambda for that FirstOrDefault – Hans Kesting May 20 '19 at 19:52
  • @JulianKock If you're going to be doing multiple lookups, I would absolutely parse the JSON once, and store two dictionaries in private fields, keyed by Id and LanguageCode respectively. As for "slower at runtime", I was only thinking about Ryan's reflection idea when I said that. There are a lot of ways to do this that wouldn't be meaningfully (or at all) slower, and in fact it's likely that the overhead of Ryan's idea wouldn't actually make the slightest difference in real life. I should have left efficiency out of it. The other considerations are far more important. – 15ee8f99-57ff-4f92-890c-b56153 May 20 '19 at 19:53
  • @JulianKock So, I should say I'd keep those two methods, but I'd change the implementations somewhat. – 15ee8f99-57ff-4f92-890c-b56153 May 20 '19 at 19:57
  • 1
    @EdPlunkett thanks for the advice and critique. I really appreciate it :-). – Julian Kock May 20 '19 at 20:00

1 Answers1

2

It seems like you're actually just wanting a way to change the comparison that's used. I would suggest just passing in a delegate for the comparison instead.

public LanguageDto GetLanguage(Func<LanguageDto, bool> isMatch)
{
    var o = JObject.Parse(json);
    var a = (JArray) o["list"];
    var _list = a.ToObject<IList<LanguageDto>>();

    return _list.FirstOrDefault(isMatch);
}

At that point, you can just define that comparison any way you choose.

LanguageDto GetLanguageById(int id) => GetLanguage(x => x.Id == id);
Chris Hannon
  • 4,134
  • 1
  • 21
  • 26