If have following classen
public interface ISomething { int Id { get; set; } }
public class SomethingA : ISomething {...}
public class SomethingB : ISomething {...}
In another class I have following two lists:
List<SomethingA> aValues;
List<SomethingB> bValues;
My question is if there is a possibility to do something like this:
public List<ISomething> GetList(bool select) {
return select ? aValues : bValues;
}
My goal is to use this as this:
GetList(true).Single(x => x.Id) // or
foreach (var value in GetList(false))
{
value.Id = 18;
}
// anything else
UPDATE:
I see, there are good possibilities. But is there also a way to also achieve the following?
GetList(true).Remove(myValue);
You can't return List<ISomething> because List<T> is not covariant and classes can't be. IEnumerable<T> is covariant, you may use it as readonly sequence.
Change the method to return IEnumerable<ISomething>
public static IEnumerable<ISomething> GetList(bool select)
{
return select ? (IEnumerable<ISomething>)aValues :bValues;
}
Then do
var result = GetList(true).Single(x => x.Id == 0);
foreach (var value in GetList(false))
{
value.Id = 18;
}
As for your update: If you like to remove the item you need to lose some flexibility. I.e Use non generic IList as the return type.
public static IList GetList(bool select)
{
return select ? (IList)aValues : bValues;
}
Then do
IList list = GetList(true);
foreach (var value in list.OfType<ISomething>())//OfType or Cast can be used
{
if (value.Id == 6)//Whatever condition
{
list.Remove(value);
break;
}
}
I like the OfType extension because it returns the typed list you need
var listA = initialList.OfType<TypeA>(); //return List<TypeA>
var listB = initialList.OfType<TypeB>(); //return List<TypeB>
So in your case you start with
var aValues = List<ISomething>.OfType<SomethingA>()
and then you can iterate on whichever subcollection you need. Of course you are then working with a IEnumerable, but that can be converted implicitly back to a IEnumerable<ITest>.
If you want to filter out values, I would create explicit methods to remove them but it depends on what you need to achieve in the end (for example comparing on a Id instead of the whole object):
public IEnumerable<T> Remove<T>(this List<IDisposable> values, T valueToRemove) where T: IComparable
{
return values.OfType<T>().Where(t => valueToRemove.CompareTo(t) != 0);
}
The simplest solution may be using Linq Cast() like this:
public List<ISomething> GetList(bool select)
{
return (List<ISomething>)(#select ? aValues.Cast<ISomething>() : bValues.Cast<ISomething>());
}
I see, there are good possibilities. But is there also a way to also achieve the following?
GetList(true).Remove(myValue);
To remove from the original lists, you are likely best of with a specialized Remove method on the class in question as others have suggested, as most solutions here return a copy of the original list.
You may remove the element from a copy of the list quite easily like so, but I understand that's not what you are asking.
var result = GetList(true);
result.Remove(myValue);
You can either use the .Cast<T> method like this:
if (select)
{
return aValues.Cast<ISomething>().ToList();
}
else
{
return bValues.Cast<ISomething>().ToList();
}
or add all items to a commong Lis() like this:
var ret = new List<ISomething>();
if (select)
{
ret.AddRange(aValues);
}
else
{
ret.AddRange(bValues);
}
return ret;
Since you only want to iterate it, I would write the method like this:
public IEnumerable<ISomething> GetList(bool select) {
return select ? aValues.Cast<ISomething>() : bValues.Cast<ISomething>();
}
You can also look at this StackOverflow question.
Related
Could someone suggest a way for me to select one of the lists within a parent list where one of it's elements has a certain property value?
public class HierarchyLevel
{
public string Abbreviation;
public string Name;
public string Value;
public Type LevelType;
public List<HierarchyLevel> Children = new List<HierarchyLevel>();
}
public static List<List<HierarchyLevel>> ElementaryTypes = new List<List<HierarchyLevel>>();
I am actually trying to get the List that has the LevelType field of a specific type.
You wrote:
I am actually trying to get the List that has the LevelType field of a specific type.
What do you want if you've got several HierarchyLevels with this LevelType? And what do you want if there are no HierarchyLevels at all with this LevelType?
Let's assume that you want all HierarchyLevels with this LevelType. If later on you only want the first, or the one with a certain Abbreviation (or whatever), you could always use .FirstOrDefault, or .Where. and do a ToList in the end.
Implementing it as an extension function. See Extension Methods Demystified
public static IEnumerable<HierarchyLevel> GetHierarchyLevelsWithLevelType(
this IEnumerable<HierarchyLevel> hierarchyLevels,
LevelType desiredLevelType)
{
foreach (var hierarchyLevel in hierarchyLevels)
{
if (hierarchyLevel.LevelType == desiredLevelType)
{ // found one!
yield return hierarchyLevel;
}
// using recursion: check all the Children
IEnumerable<HierarchyLevel> childrenWithDesiredLevelType = hierarchyLevel.Children
.GetHierarchyLevelsWithLevelType(desiredLevelType);
foreach(var childWithDesiredLevelType in childrenWithDesiredLevelType)
{
yield return childWithDesiredLevelType;
}
}
}
Because of the recursion all Grandchildren and their Children etc will be returned
usage:
var allSpecialHierarchies = myHierarchies.GetHierarchyLevelsWithLevelType(LevelType.Special);
// get the first:
var firstSpecialHierarchy = allSpecialHierarchies.FirstOrDefault();
// get the first three named "Shakespeare:
var threeShakesPeares = allSpecialHierarchies
.Where(hierarchyLevel => hierarchyLevel.Name == "Shakespeare")
.Take(3)
For better usage you should provide a version that has a parameter IQualityComparer<LevelType>. Let the function above call that one.
And a nice challenge: to be fully LINQ compatible, create a version with a predicate that returns a type T and an equality comparer for this type T, so that you can have all HierarchyLevels with a certain Name, or Abbreviation.
You can Solve your with the help of recursion consider example below :- I have taken sample type of String you can use any of your Type
List<List<HierarchyLevel>> sample = new List<List<HierarchyLevel>>();
Type yourType = typeOf(string);
List<HierarchyLevel> filtered = sample.Where(x => ContainsElement(x, yourType));
public void bool ContainsElement(List<HierarchyLevel> list,Type yourType)
{
if(list.Any(x => x.LevelType == yourType) //check if current node has same level type
return true;
else if(list.Childern.Count > 0) //check if current node has children if yes then call ContainsElement again
return list.Children.Any(x => ContainsElement(x,yourType));
else
return false; //else return false in last
}
Thanks to user743414 for pointing out how simple this was :)
By using a dictionary instead, I could reference to the specific list. (This is also a faster option.)
Dictionary<Type,List<HierarchyLevel>> HierarchicalData;
I can now use it with a key of 'Type':
private void UpdateGeneralData(object Entity, Dictionary<Type,List<HierarchyLevel>> TypeData)
{
CBType.Items.Clear();
foreach (var item in TypeData[Entity.GetType()])
{
CBType.Items.Add(item);
}
}
Something like this (?):
List<HierarchyLevel> var = hLevel.Select(h => h.Children.Where(c => c.Param = "desired param")).ToList();
Right now my code looks like this:
var ids = projectId.HasValue ? new List<Guid> { projectId.Value } : new List<Guid>();
Is there a more succinct way of creating a list in one line of code, with one element added optionally?
Another idea for an extension method (the name could definitely be improved, maybe PossiblyCreateSingletonList?):
public static class NullableExtensions
{
public static List<T> SingletonList<T>(this Nullable<T> item) where T : struct
{
return item.HasValue ? new List<T> { item.Value } : new List<T>();
}
}
Usage:
Guid? projectId = null;
List<Guid> projectIds = projectId.SingletonList(); // empty list
I would solve this using a extension method like this:
public static void AddIfNotNull<T>(this List<T> list, T? value) where T : struct
{
if(value != null)
{
list.Add(value.Value);
}
}
Than it could be used like this:
var ids = new List<Guid>();
ids.AddIfNotNull(projectId);
Maybe not as "crafty" (and not a one-liner) as your proposal, but in my opinion it is much easier to read and understand. If desired to be used as a one-liner you could modify the return type of the extension to be the list. That would make it possible to be used something like var ids = new List<Guid>().AddIfNotNull(projectId);
This probably isn't a good idea, but in C# 6, collection initializers also work when Add() is an extension method.
This means you can write the extension Add() like this:
public static void Add<T>(this List<T> list, T? item) where T : struct
{
if (item.HasValue)
{
list.Add(item.Value);
}
}
And then this code will do what you want:
var list = new List<Guid> { projectId };
Note that this will only work for value types (because of the T/T? distinction) and there is no simple way to make it work for reference types.
Also, I would find the line above very surprising, being more succinct is not always better. Which is why I actually wouldn't use this code.
That's pretty succinct, but another option would be to use LINQ:
var ids = new[] { projectId }.Where(x => x.HasValue).Select(x => x.Value).ToList();
If you're going the extension method route, it would have to look something like:
public static void AddIfNotNull<T>(this List<T> list, T? value)
where T : struct
{
if (value.HasValue)
{
list.Add(value.Value);
}
}
You'd have to build a second extension method for reference types (where T : class) if you needed.
This code doesn't work, but:
public virtual ICollection<SomeItem> items { get { return (ICollection<SomeItem>)items.Where(e => e.isVisible == true); } set { ;} }
I'd like to do something to that effect. So to get an ICollection filtered by a property of the collection's elements.
Sure, I could iterate through the elements, and get the right ones, put them in a new collection and return with that, but is there a nicer solution?
Perhaps what you're looking for is an Extension Method?
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.
public static class ExtensionMethods
{
public static ICollection<SomeItem> OnlyVisible(this ICollection<SomeItem) items) {
return items.Where(e => e.isVisible).ToList();
}
}
Note that Where returns an IEnumerable, which you cannot modify, so I call ToList() which essentially does everything in your last sentence.
You would then use it like this:
void Foo(ICollection<SomeItem> items) {
foreach (var i in items.OnlyVisible()) {
// Use i
}
}
Try:
items.Where(e => e.isVisible == true).ToList()
So I'm new to generics. But generics seem like a great way to reduce code. here is the scenario. I have a MVC Web API.
http://www.google.com/{controller}/{chartType}/{id}
NOTE: id is optional
I have several chart types which return similar objects:
HourlyDeviceChart
HourlyUsersCharrt
HourlyAvgProcessingTime
etc..
I would like to have just one method that evaluates the chart type parameter and executes the corresponding actions. instead of 8 or 10 methods.
I would be accepting if my design needs some refactoring. I'm open to suggestions. The idea here is to reduce some code. I would hate to have 10 methods exposed in the Web API and then 10 more corresponding methods in another class. Just seems redundant.
As always your suggestions are welcomed!
The method exposed by the API:
IEnumerable<T> GetChart(string chartType)
{
switch(chartType)
{
case "DeviceChart":
return repository.HourlyDeviceChart();
break;
case "UserChart":
return repository.HourlyUsersChart();
break;
}
}
//Then the class that handles all the work would look something like the below
IEnumerable<HourlyDeviceChart> HourlyDeviceChart()
{
// select appropriate items from the queue
// populate HourlyDeviceChart object
// add object to list
// return HourlyDeviceChart list
}
IEnumerable<UserDeviceChart> HourlyUsersChart()
{
// do more of the same
}
You can use generics like this:
interface IChart {
bool IsCharItemNeeded(IChartItem item);
void AddChartItem(IChartItem item);
}
IEnumerable<T> Charts<T>() where T : new, IChart {
var res = List<T>();
foreach (QueueCommand command in MyBigQueue) {
var chart = new T();
foreach (IChartItem item in command) {
if (chart.IsCharItemNeeded(item)) {
chart.AddChartItem(item);
}
}
res.Add(chart);
}
return res;
}
All chart types need to implement the common IChart interface. The where T : new, IChart line provides a constraint that lets you call new T(); for that, all chart classes must also implement a no-argument constructor.
Now you can use your generic code like this:
IEnumerable<UserChart> userCharts = Charts<UserChart>();
IEnumerable<DeviceChart> deviceCharts = Charts<DeviceChart>();
If both HourlyUserChart and HourlyDeviceChart methods work in same fashion, then dasblinkenlight's answer is good, you can have one generic way of populating them. If you need to populate them differently in two repository methods, may be something like these will do:
1)
interface IHourlyChart {
IEnumerable<IHourlyChart> Create();
}
class HourlyDeviceChart : IHourlyChart
{
public IEnumerable<IHourlyChart> Create()
{
return repository.HourlyDeviceChart();
}
}
class HourlyUsersChart : IHourlyChart
{
public IEnumerable<IHourlyChart> Create()
{
return repository.HourlyUsersChart();
}
}
IEnumerable<T> GetChart<T>() where T : IHourlyChart, new()
{
return (IEnumerable<T>)new T().Create();
}
2) Or make it a tad more strongly typed via generics.
interface IHourlyChart<T> where T : IHourlyChart<T> {
IEnumerable<T> Create();
}
class HourlyDeviceChart : IHourlyChart<HourlyDeviceChart>
{
public IEnumerable<HourlyDeviceChart> Create()
{
return repository.HourlyDeviceChart();
}
}
class HourlyUsersChart : IHourlyChart<HourlyUsersChart>
{
public IEnumerable<HourlyUsersChart> Create()
{
return repository.HourlyUsersChart();
}
}
IEnumerable<T> GetChart<T>() where T : IHourlyChart, new()
{
return new T().Create();
}
3) Or some reflection, which is still better than your type checking:
IEnumerable<T> GetChart<T>() where T : IHourlyChart, new()
{
//find necessary method and invoke. may be:
return repository.GetType()
.GetMethods()
.Single(x => x.ReturnType == typeof(IEnumerable<T>))
.Invoke(repository, new object[0]) as IEnumerable<T>;
}
4) Worst case, do type checking inside your generic method, but check on the type itself, not any magic strings which is very brittle.
IEnumerable<T> GetChart<T>()
{
if (typeof(T) == typeof(HourlyDeviceChart))
return (IEnumerable<T>)repository.HourlyDeviceChart();
else if (typeof(T) == typeof(HourlyUsersChart))
return (IEnumerable<T>)repository.HourlyUsersChart();
// throw;
}
Call them all like:
var chartables = GetChart<HourlyUserChart>(); //etc
You should be able to do this by using a new interface and applying a constraint to your method GetChart
//Interface with a Type parameter to specify the return type of the method
public interface IChart<T>
{
IEnumerable<T> HourlyChart();
}
//How to implement the interface
public class HourlyDeviceChart : IChart<HourlyDeviceChart>
{
public static IEnumerable<HourlyDeviceChart> HourlyChart()
{
//Do work
}
}
//Your new method with a constraint applied
IEnumerable<T> GetChart<T>(string chartType) where T : IChart<T>
{
return T.HourlyChart();
}
I've been struggling a bit with this tiny problem - and I'm quite sure there's an "easy" solution.
I have a generic nHibernate base-repository class with the following method:
public IList<T> GetAll()
{
using (var session = SessionProvider.OpenSession())
{
return session.Query<T>().ToList();
}
}
However - I'm trying to control my model by using some very simple interfaces. I have an interface - ISetDeleted:
public interface ISetDeleted
{
bool Deleted { get; set; }
}
In my GetAll()-method I would like to check it the current type implements this interface - and if it does, only return the entities that are not marked as deleted:
public IList<T> GetAll()
{
using (var session = SessionProvider.OpenSession())
{
if (typeof(T) is ISetDeleted)
{
// Only retrieve entities that are not marked as deleted
// WHAT DO I DO HERE?
}
return session.Query<T>().ToList();
}
}
I know I could just retrieve all the entities and loop through these - but I would prefer a cleaner approach - e.g. an expression that implements the check (if possible).
It would be very much appreciated if someone could help me out with this :)
First
typeof(T) is ISetDeleted
will only return true if the type parameter is ISetDeleted, not if it implements the interface. You probably want
if (typeof(ISetDeleted).IsAssignableFrom(typeof(T)))
Second, I think you want
return session.Query<T>().Where(x => !((ISetDeleted)x).IsDeleted).ToList();
You can use Linq (namespace System.Linq):
public IList<T> GetAll()
{
using (var session = SessionProvider.OpenSession())
{
if (typeof(ISetDeleted).IsAssignableFrom(typeof(T)))
{
return session.Query<T>().Where(o => !(ISetDeleted) o).Deleted).ToList();
}
else
{
return session.Query<T>().ToList();
}
}
}
If you can write it like this, it will be easier to extend in future and also allow you to add additional constraints:
public IList<T> GetAll()
{
using (var session = SessionProvider.OpenSession())
{
var query = session.Query<T>();
if (typeof(ISetDeleted).IsAssignableFrom(typeof(T)))
{
query = query.Where(x => !(ISetDeleted)x).Deleted);
}
return query.ToList();
}
}
which should work provided that session.Query returns an IQueryable