Order readonly List - c#

I have a readonly List so I can hide the Add method from other classes, like this:
class Foo
{
private readonly List<Bar> _Bars = new List<Bar>;
public()
{
this.Bars = _Bars.AsReadOnly();
}
public ReadOnlyCollection<Bar> Bars
{
get;
private set;
}
public void AddBar(Vector Dimensions)
{
_Bars.Add(new Bar(Dimensions));
}
}
The thing is, now I want to order the _Bars field of an instance of Foo, like such:
public void OrderBarsByVolume()
{
_Bars.OrderByDescending(o => o.Volume); //Doesn't do anything
_Bars = _Bars.OrderByDescending(o => o.Volume).ToList(); //Error: A readonly field cannot be assigned to
}
Is it possible to use orderby and keep the add feature of the List hidden from other classes?

Use List<T>.Sort method
_Bars.Sort((x,y) => x.Volume.CompareTo(y.Volume));

Not with your current implementation, however, if you adjust things slightly then yes you can. The idea of "hiding" the underlying data means you don't have to hold it internally as read only but rather expose it as read only
private List<Bar> _Bars = new List<Bar>();
public ReadOnlyCollection<Bar> Bars
{
get { return _Bars.AsReadOnly(); }
}
public void OrderBy(Func<Bar, bool> src)
{
_Bars = _Bars.OrderByDescending(src);
}
...
var foo = new Foo();
foo.OrderBy(x => x.Volume);
If you feel creating a new ReadOnlyCollection each time is too expensive then keep your code as it is but simply remove the readonly modifier
private List<Bar> _Bars = new List<Bar>;
public void OrderBy(Func<Bar, bool> src)
{
_Bars = _Bars.OrderByDescending(src).ToList();
}

Add a public method that will do the ordering within the Foo object.

Even if James gave you some good tips, there are still some open issues.
So let's start with your implementation:
private readonly List<Bar> _Bars = new List<Bar>;
This won't make the list itself read-only. Still it is possible to add, remove an item or to clear the entire list. The keyword readonly only ensure that you can't replace the whole list by a completely different list.
So what you like, is that within your class you have full access to the list (so Foo can add, remove, sort items), but anybody who requested the list, can only read this list. The open question here would be what should happen if someone requested the list and afterwards the list was changed from Foo. Should the already outgiven list reflect theses changes or not? Mostly you like this behaviour, but it really depends on what you like to achieve.
Here is my code example that should solve most of your problems:
internal class Foo
{
// The list which can be manipulated only be Foo itself.
private List<Bar> _Bars;
// The proxy that will be given out to the consumers.
private ReadOnlyCollection<Bar> _BarsReadOnly;
public Foo()
{
// Create the mutable list.
_Bars = new List<Bar>();
// This is a wrapper class that holds a
// reference to the mutable class, but
// throws an exception to all change methods.
_BarsReadOnly = _Bars.AsReadOnly();
}
public IReadOnlyList<Bar> Bars
{
// Simply give out the wrapper.
get { return _BarsReadOnly; }
}
public void AddBar(Vector dimensions)
{
// Manipulate the only intern available
// changeable list...
_Bars.Add(new Bar(dimensions));
}
public void SortBars()
{
// To change the order of the list itself
// call the Sort() method of list with
// a comparer that is able to sort the list
// as you like.
_Bars.Sort(BarComparer.Default);
// The method OrderBy() won't have any
// immediate effect.
var orderedList = _Bars.OrderBy(i => i.Volume);
// That's because it will just create an enumerable
// which will iterate over your given list in
// the desired order, but it won't change the
// list itself and so also not the outgiven wrappers!
}
}
To use the Sort() method of the list class you need an comparer but that's quite easy to implement:
internal class BarComparer : IComparer<Bar>
{
public static BarComparer Default = new BarComparer();
public int Compare(Bar x, Bar y)
{
if (ReferenceEquals(x, y))
return 0;
if (ReferenceEquals(x, null))
return -1;
if (ReferenceEquals(y, null))
return 1;
return x.Volume.CompareTo(y.Volume);
}
}
I hope this gives you a little more enlightenment about how stuff in C# works.

Let the callers handle the sorted list:
public IEnumerable<Bars> OrderedBars(Func<Bar, bool> sortMethod)
{
return _Bars.OrderBy(sortMethod);
}
If you really want to keep the sorted bars to yourself, you could create a immutable class where ordering the bars create a new instance of Foo which will then either replace the current one or be used by the caller, something like that:
public Foo OrderBarsByVolume()
{
return new Foo() {_Bars = this._Bars.OrderByDescending(o => o.Volume)}
}

Related

Initialize Lazy<T> with a known Value

Question (TL;DR) in this constructor:
internal AnimalCollection(IReadOnlyList<Animal> animals, AnimalFlags aggregatedFlags)
{
AnimalList = animals;
_lazyAggregatedFlags = new Lazy<AnimalFlags>(() => aggregatedFlags);
var temp = _lazyAggregatedFlags.Value; // <<< ensure IsValueCreated == true
}
How can I avoid the overhead of initializing a brand new instance of Lazy just to immediately evaluate it, causing it to tear down most of the internal structures it just created, similar to Task.FromResult(...) when using tasks?
Context and further details:
Suppose I have an object representing a collection of animals (this is a re-mapping of my actual code to something question-friendly, so apologies that the structure is a bit odd for describing animals...).
[Flags]
enum AnimalFlags
{
Carnivorous = 1,
Prey = 2,
// etc.
}
public abstract class Animal
{
internal abstract AnimalFlags Flags { get; }
public bool IsCarnivorous => (Flags & AnimalFlags.Carnivorous) != 0;
// etc.
}
public class AnimalCollection
{
internal AnimalCollection(IReadOnlyList<Animal> animals)
{
AnimalList = animals;
}
public IReadOnlyList<Animal> AnimalList { get; }
}
public static class AnimalHelper
{
// Caller is expected to provide a known and immutable list of animals (not merely read-only)
// This simply wraps it up as an AnimalCollection.
static AnimalCollection GetAnimalCollection(IReadOnlyList<Animal> animals) => new AnimalCollection(animals);
// Caller supplies animals, we create an animal collection from them and must enumerate all animals in the process.
static AnimalCollection CreateAnimalCollection(IEnumerable<Animal> animals)
{
return GetAnimalCollection(animals.ToList());
}
}
GetAnimalCollection is used extensively in existing code. There are very large collections of existing animals, where we want to pre-populate an animal collection using one. Also assume some other classes implementing IReadOnlyList that allow subsets to be selected without enumerating the whole list, etc.
Rather than enumerating all animals in the collection that allows callers to completely skip the collection if it doesn't contain any carnivorous animals, I'd like to add a property to the AnimalCollection. A naive implementations could add a simple property like:
public bool IsAnyCarnivorous => AnimalList.Any(a => a.IsCarnivorous);
But it makes more sense to aggregate the flags once, using Lazy, for example:
public class AnimalCollection
{
internal AnimalCollection(IReadOnlyList<Animal> animals)
{
AnimalList = animals;
_lazyAggregatedFlags = new Lazy<AnimalFlags>(() => AnimalList.Aggregate(default(AnimalFlags), (flags, animal) => flags | animal.Flags));
}
Lazy<AnimalFlags> _lazyAggregatedFlags;
public bool IsAnyCarnivorous => (_lazyAggregatedFlags.Value & AnimalFlags.Carnivorous) != 0;
public IReadOnlyList<Animal> AnimalList { get; }
}
However, when using CreateAnimalList, we now enumerate the list twice - once to create the list, and again to get the aggregated flags. That's a little inefficient, so we can change the ToList() shortcut to build the list ourselves and get the aggregated flags at the same time:
static AnimalCollection CreateAnimalCollection(IEnumerable<Animal> animals)
{
var animalsList = new List<Animal>((animals as ICollection)?.Count ?? (animals as IReadOnlyList<Animal>)?.Count ?? 0);
AnimalFlags aggregatedFlags = 0;
foreach(var animal in animals)
{
animalsList.Add(animal);
aggregatedFlags |= animal.Flags;
}
return GetAnimalCollection(animalsList, aggregatedFlags);
}
Adding a new constructor to AnimalCollection:
internal AnimalCollection(IReadOnlyList<Animal> animals, AnimalFlags aggregatedFlags)
{
AnimalList = animals;
_lazyAggregatedFlags = new Lazy<AnimalFlags>(() => aggregatedFlags);
var temp = _lazyAggregatedFlags.Value; // <<< ensure IsValueCreated == true
}
This constructor could also be used in other contexts, such as when combining collections of animals (and therefore combining their aggregated flags), which can then be very quick operations.
However, it seems to have made a bit more work for itself than necessary.
If, instead of Lazy<T>, I'd been using a Task<T>, I would be able to use Task.FromResult(aggregatedFlags) to avoid the additional overhead of creating a complex object to contain an already-known value. I can't see an equivalent way to instantiate a Lazy<T> from a known value already in hand. Am I missing something?
Best answer I came up with myself after the initial discussion, from reviewing a little more documentation and the reference source is to add LazyThreadSafetyMode.None, which avoids a tiny amount of overhead from acquiring a lock.
internal AnimalCollection(IReadOnlyList<Animal> animals, AnimalFlags aggregatedFlags)
{
AnimalList = animals;
_lazyAggregatedFlags = new Lazy<AnimalFlags>(() => aggregatedFlags, System.Threading.LazyThreadSafetyMode.None);
var temp = _lazyAggregatedFlags.Value; // <<< ensure value created on this thread before returning
}
This can be wrapped in a helper method:
public static class LazyHelper
{
public static Lazy<T> FromValue<T>(T value)
{
var result = new Lazy<T>(() => value, System.Threading.LazyThreadSafetyMode.None);
var tmp = result.Value; // <<< ensure value created on this thread before returning
return result;
}
}
... simplifying the constructor to:
internal AnimalCollection(IReadOnlyList<Animal> animals, AnimalFlags aggregatedFlags)
{
AnimalList = animals;
_lazyAggregatedFlags = LazyHelper.FromValue(aggregatedFlags);
}
The overhead of wrapping a value in a Lazy<T> is orders of magnitude less than the overhead involved in Task.Run(() => value), which perhaps explains why the latter has a pre-existing Task.FromResult(value). #Corak mentioned in chat that if you're working with .Net Core, [Lazy<T> has] a constructor that takes the T directly. This seems to me a syntax that would be likely to give confusion given other questions I've seen about Lazy<T> (e.g. someone may call the non-lazy constructor expecting it to work lazily)
In any case, absent anything obvious I've overlooked, I don't need to continue with nano-optimisations.

Why my method changes the original value of the object that is passed to it?

I have the following object
var filters = new List<IReportFilter>
{
new ReportFilter
{
ReportColumn = new ReportColumn{ ColumnKey = "Result.IsCompleted"},
Value = "1",
SubFilters = new List<IReportFilter>
{
new ReportFilter { SqlOperator = FilterOperator.Or, ReportColumn = new ReportColumn{ ColumnKey = "User.LastName"}, Value = "Alhayek"},
new ReportFilter { SqlOperator = FilterOperator.Or, ReportColumn = new ReportColumn{ ColumnKey = "User.LastName"}, Value = "Smith"},
new ReportFilter { SqlOperator = FilterOperator.Or, ReportColumn = new ReportColumn{ AggregateFunction = SqlAggregateFunctions.Count}, Type = FilterType.GreaterThenOrEqualTo ,Value = "0" },
}
},
};
The obove object is passed to another class using a method like so
IReportModel ReportModel = Template.CreateReport();
ReportModel.Get(filters);
Inside the the Get method of the ReportModel class I want to loop through the filters list and create a new list without changing the original list. the new list will become a subset of the original.
From with in my Get method here is what I have done
public SqlCommand Build(List<IReportFilter> filters)
{
var a = CloneFilters(filters);
var b = CloneFilters(filters);
List<IReportFilter> standardFilters = ExtractFiltersByAType(a, true);
List<IReportFilter> aggregateFilter = ExtractFiltersByAType(b, false);
}
But every time I execute the method ExtractFiltersByAType the value of a,b, and filters change to equal the same value of aggregateFilter.
I am NOT expecting for any of the variables to change. But they are for some reason that I don't understand.
Here is my CloneFilters method
private List<IReportFilter> CloneFilters(List<IReportFilter> myFilters)
{
List<IReportFilter> copyOfFilters = new List<IReportFilter>();
foreach (var myFilter in myFilters)
{
copyOfFilters.Add(myFilter);
}
return copyOfFilters;
}
And here is my ExtractFiltersByAType
private List<IReportFilter> ExtractFiltersByAType(List<IReportFilter> filtersSource, bool IsStandard = true)
{
List<IReportFilter> validFilters = new List<IReportFilter>();
foreach (var filterSource in filtersSource)
{
if (filterSource.SubFilters != null && filterSource.SubFilters.Any())
{
filterSource.SubFilters = ExtractFiltersByAType(filterSource.SubFilters, IsStandard); //I think this what could be causing this problem
}
if ((IsStandard && !filterSource.ReportColumn.IsAggregate) || (!IsStandard && filterSource.ReportColumn.IsAggregate))
{
validFilters.Add(filterSource);
}
}
return validFilters;
}
Question
Since I am not using ref to pass the object by reference to the method, why is my function changing the value to original object?
When passing a list of object to method in c#, will the system create a copy or will it passes the object by reference?
How can I solve this problem so that every time I execute ExtractFiltersByAType method, only the copy is changed not the originals?
I am thinking that the line filterSource.SubFilters = ExtractFiltersByAType(filterSource.SubFilters, IsStandard); in the ExtractFiltersByAType is causing the problem but I don't understand why and how.
Without ref
When you pass a reference type as an argument (which includes a list), you pass a copy of the reference to that object. This means you can change your object attributes, but can't change the object itself.
Example:
public class Program
{
static void Main(string[] args)
{
Foo foo = new Foo(1);
Console.WriteLine(foo.Bar);
// This will change foo.Bar
ChangeFoo(foo, 5);
Console.WriteLine(foo.Bar);
// Does not change foo
DoesNotChangeFoo(foo, 10);
Console.WriteLine(foo.Bar);
Console.Read();
}
static void ChangeFoo(Foo foo, int newValue)
{
// Since it receives a copy of the reference to Foo, it actually changes foo.Bar value
foo.Bar = newValue;
}
static void DoesNotChangeFoo(Foo foo, int newValue)
{
// Since it receives a copy of the reference to foo, it only updates this method's reference, not changing the caller's reference
foo = new Foo(newValue);
}
}
public class Foo
{
public Foo(int bar)
{
Bar = bar;
}
public int Bar { get; set; }
}
With ref
If you wanted to change the caller's object reference, you would need to pass the actual reference used by the calle's, that's when you use the ref keyword.
Example:
public class Program
{
static void Main(string[] args)
{
Foo foo = new Foo(1);
Console.WriteLine(foo.Bar);
// This will change foo's object reference
ChangeFooObjectReference(ref foo, 15);
Console.WriteLine(foo.Bar);
Console.Read();
}
static void ChangeFooObjectReference(ref Foo foo, int newValue)
{
// SInce you are receiving the actual reference used by the caller, you actually change it's own reference
foo = new Foo(newValue);
}
}
public class Foo
{
public Foo(int bar)
{
Bar = bar;
}
public int Bar { get; set; }
}
Your case
As you correcly assumed, the main cause of your problem is this line:
filterSource.SubFilters = ExtractFiltersByAType(filterSource.SubFilters, IsStandard);
This line actually changes this object's SubFilters.
But it's worth noting that you may have some bigger problems in you Clone method.
private List<IReportFilter> CloneFilters(List<IReportFilter> myFilters)
{
List<IReportFilter> copyOfFilters = new List<IReportFilter>();
foreach (var myFilter in myFilters)
{
copyOfFilters.Add(myFilter);
}
return copyOfFilters;
}
This method return's a new List, but the content of that list is exactly the same as the argument's. This means that, if you change any of the object's contained in the object used as an argument, you change it in the new List too.
Here's an example of what's happening.
static void Main(string[] args)
{
List<Foo> foos = new List<Foo>();
foos.Add(new Foo(2));
List<Foo> newFoo = CreateNewFoo(foos);
Console.WriteLine(newFoo.First().Bar);
foos.First().Bar = 5;
// Since we changed the first object of the old list, and it is the same object in the new list, we will get the new result.
Console.WriteLine(newFoo.First().Bar);
Console.Read();
}
static List<Foo> CreateNewFoo(List<Foo> foos)
{
List<Foo> newFoos = new List<Foo>();
foreach(Foo foo in foos)
{
newFoos.Add(foo);
}
return newFoos;
}
I would suggest implementing the ICloneable interface in your IReportFilter interface, and each concrete class implementing IReportFilter.
ICloneable implements a single method Clone(), which returns an object. This method should create a new instance of the same class in which it's implemented, containing a new object identical to the current object. Than you would change your method to:
private List<IReportFilter> CloneFilters(List<IReportFilter> myFilters)
{
List<IReportFilter> copyOfFilters = new List<IReportFilter>();
foreach (var myFilter in myFilters)
{
copyOfFilters.Add(myFilter.Clone() as IReportFilter);
}
return copyOfFilters;
}
As for implementing the ICloneable inteface, refer to this question:
Proper way to implement ICloneable
Edit
As mentioned by user muratgu in the question comments, your CloneFilter method is doing a shallow copy of your list, what you are looking for is a deep copy. That could be implemented with the aforementioned ICloneable interface.
The only thing that ref does is determine whether the method receiving the parameter can modify the variable passed to it. In the case of an object, that means setting the variable to a different object or setting it to null.
But even if you don't use ref, the method you pass the parameter to can can set its properties or call methods which modify the state of that object. That's normal and expected. When you pass an object to another method, it's not just so that the other method can read its properties. You might also want that method to operate on that object in some way that modifies it.
The simplest example is a List<T>. If you pass a List<string> to another method - without using ref - that other method can add items to the list, modify items in the list, clear the list, etc.
The only difference with using ref is that if the method you pass the variable to sets the variable to a different list or sets it to null, it's going to modify the variable in the method that passed the argument.
Most of the time we don't want a method we call to completely replace the variable we pass in. If we wanted a new object we'd write a function that returns an object, not one that replaces the variable we passed in.

How can I get a unique id for a List<T>

I have a List<T>, where T is a class that has an int field for an id. How is the best way to get a unique id value that has not been used in any of the objects in the List<T>?
How is this procedure normally coded? Is there a data type that can help with this or do I need to store the largest id value?
EDIT
How about when I get an id for an object that is 1. I then delete the object from the List. When I create a new object, I would like the unique id to be 2. In this situation, is there any better way than to store the last unique id?
Thanks.
For that approach I'd write an inherited class of List<T> which holds the logic, so you wouldn't need to implement it everywhere you access the list.
You can even leave it generic if you have a minimum interface which has the Id value.
interface IWithId {
int Id { get; set; }
}
class CustomList<T> : List<T> where T : class, IWithId {
private lastUsedId = 1;
public void AddObjectWithAutomaticId(T newObject) {
newObject.Id = lastUsedId++;
base.Add(newObject);
}
public T GetElementById(int id) {
return base.SingleOrDefault(p => p.Id == id);
}
}
The Remove method would still work as before. The class stores the last used Id, independent what you remove. The Add method is also still available, when you want to add an object with a given Id and not auto-fill it.
I agree with the comment that a GUID would suit you as an id property. If, however, you need to use an int then I suggest a new class.
The problem with inheriting List<T> is that you would have to override multiple methods to ensure that things such as Add(), AddRange(), Insert() can't add duplicate ids and update the stored maximum id. It would be easy to miss one.
I would use a class which doesn't inherit anything, but uses a dictionary internally. This won't have all the same methods as a List<T>, but that's not necessarily a bad thing - it saves mistakes being made and you can have a ToList() method for when they want to query it as if it was a List<T>.
Using part of a previous answer to ensure that T has an Id property gives:
interface IHasId {
int Id { get; set; }
}
class AutoIdList<T> where T : class, IHasId {
private readonly IDictionary<int, T> _dictionary = new Dictionary<int, T>();
//Using this list ensures you don't duplicate ids even
//for an item added with an explicit id then removed
private IList<int> _historicalIds = new List<int>();
private int highestAutoGeneratedId = 0;
public List<T> ToList() {
return _dictionary.Values.ToList();
}
public void Add(T item, bool generateId) {
if (generateId) {
highestAutoGeneratedId = NextId();
T.Id = highestAutoGeneratedId;
}
Add(T);
}
public void Replace(T item) {
_dictionary[item.Id] = item;
}
public void Remove(T item) {
_dictionary.Remove(item.Id);
}
private void Add(T item) {
if (_historicalIds.Contains(T.Id)) {
//throw an appropriate exception
} else {
_historicalIds.Add(T.Id);
_dictionary.Add(T.Id, T);
}
}
private int NextId() {
var id = highestAutoGeneratedId + 1;
while (_historicalIds.Contains(id)) {
id++;
}
return id;
}
//More methods to simulate AddRange, Insert, etc if required. Leave if not.
//Should all have simple logic but require checking of Id if adding anything
//Also need logic to maintain the list of used ids
}

Creating a non-static version of compiler-based "dictionary" where keys are types

There is a very easy trick which creates a dictionary-like structure where keys are types.
The structure acts like a Dictionary<Type, T?> where keys are Type objects and values are instances of the corresponding types.
This wonderful structure is as fast as just a variable or array since the "lookup" is only done once by the compiler/JITter and the proper value reference is compiled into your program.
public static class MyDict<T> {
public static T Value { get; set; }
}
You can work with that structure like this:
MyDict<string>.Value = MyDict<int>.Value.ToString();
The problem is that this "dictionary" is global. The only way to create different dictionaries is to create different classes.
How can create a similar (fastest "lookup", no boxing) non-static structure? (Without code generation.)
Simply said: I want to have multiple Dictionary<Type, object>-like objects without lookup costs, casting and boxing.
Here's an approach that extends the method described in the question:
public class TypeDict
{
public T Get<T>()
{
return MyDict<T>.Values[this];
}
public void Set<T>(T value)
{
MyDict<T>.Values[this] = value;
}
private static class MyDict<T>
{
public static Dictionary<TypeDict, T> Values { get; private set; }
static MyDict()
{
Values = new Dictionary<TypeDict, T>();
}
}
}
Now we can use the TypeDict like this:
void X()
{
var a = new TypeDict();
var b = new TypeDict();
a.Set<int>(1);
a.Set<double>(3.14);
a.Set("Hello, world!");
//Note that type inference allows us to omit the type argument
b.Set(10);
b.Set(31.4);
b.Set("Hello, world, times ten!");
Console.WriteLine(a.Get<int>());
Console.WriteLine(a.Get<double>());
Console.WriteLine(a.Get<string>());
Console.WriteLine();
Console.WriteLine(b.Get<int>());
Console.WriteLine(b.Get<double>());
Console.WriteLine(b.Get<string>());
}
Ark-kun is using generics to essentially generate unique types at compile time. With a generic type, any static members are unique to that specific closed generic type. This way it's processed as fast as a standard static member lookup.
The above usage is equivalent to something like this:
public static class MyDict_String
{
public static string Value { get; set; }
}
public static class MyDict_Int32
{
public static int Value { get; set; }
}
MyDict_String.Value = MyDict_Int32.Value.ToString();
AFAIK, types are "static" (in that you can't define more than one that way) so I don't know of a way to cheat around this and maintain the same performance of a statically compiled member lookup.
Your best bet otherwise (I think) is to create a generic instance type that wraps its own dictionary that uses System.Type for its keys and System.Object for its values to which you have to perform boxing/casting when inserting/retrieving values.
EDIT: Here's a simple implementation wrapping a dictionary:
public class MyTypedDict
{
private Dictionary<Type, object> Values = new Dictionary<Type, object>();
public T Get<T>()
{
object untypedValue;
if (Values.TryGetValue(typeof(T), out untypedValue))
return (T)untypedValue;
return default(T);
}
public void Set<T>(T value)
{
Values[typeof(T)] = value;
}
}
Thinking about it more, it might be possible to achieve a more property-like syntax using an ExpandoObject (http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx) through some tomfoolery, but I feel like this would be pretty abusive and I can only assume terribly prone to runtime errors. (plus it would afford you nothing at compile time)
EDITx2: If you really want to have different sets of values, you could nest it within another generic type:
public static class ValueSets<T>
{
public static class MyDict<U>
{
public static U Value { get; set; }
}
}
With usage like:
ValueSets<int>.MyDict<string>.Value = "Hello ";
ValueSets<bool>.MyDict<string>.Value = "World!";
string helloworld = ValueSets<int>.MyDict<string>.Value + ValueSets<bool>.MyDict<string>.Value;
Console.WriteLine(helloworld);//Hello World!
But then the initial type int and bool in this case become "magical" and without meaning, plus you would need to provide a unique type per distinct set of values you'd like to use. Plus you could not pass it around and modify as an instance variable, rather it'd be statically accessible (so long as you have access to use the type T). So perhaps you could declare minimally visible types that are named with meaning and use those:
internal class MyFirstWords {}
internal class MySecondWords {}
ValueSets<MyFirstWords>.MyDict<string>.Value = "Hello ";
ValueSets<MySecondWords>.MyDict<string>.Value = "World!";
string helloworld = ValueSets<MyFirstWords>.MyDict<string>.Value + ValueSets<MySecondWords>.MyDict<string>.Value;
Console.WriteLine(helloworld);//Hello World!
Regardless, I think this is quite wacky and I wouldn't recommend it.
A more complicated version. Don't know if it's closer:
Define a generic dictionary:
public class MyDictionary<T>
{
Dictionary<string, T> dict;
public MyDictionary()
{
dict = new Dictionary<string, T>();
}
public T this[string name]
{
get
{
if (dict.ContainsKey(name))
return dict[name];
else
return default(T);//or throw
}
set
{
dict[name] = value;
}
}
}
Then a repository to store those dictionaries:
public class MyRepository
{
List<object> repo;
public MyRepository()
{
repo = new List<object>();
}
public void Add<T>(string name, T value)
{
if (!repo.OfType<MyDictionary<T>>().Any())
repo.Add(new MyDictionary<T>());
var dict = repo.OfType<MyDictionary<T>>().FirstOrDefault();
dict[name] = value;
}
public T GetValue<T>(string name)
{
if (!repo.OfType<MyDictionary<T>>().Any())
return default(T);//or throw
else
{
var dict = repo.OfType<MyDictionary<T>>().FirstOrDefault();
return dict[name];
}
}
}
And finally you may use this repository:
MyRepository repo = new MyRepository();
repo.Add("A", 1);
repo.Add("B", 1);
int i = repo.GetValue<int>("A") + repo.GetValue<int>("B");
In this example, there is MyDictionary<T> boxing to object is left.
From the other side, if your are working with some certain types you may not use thie repository class at all. But utilize separate dictionaties.
MyDictionary<int> intDict = new MyDictionary<int>();
intDict["A"] = 1;
intDict["B"] = 2;
int i = intDict["A"] + intDict["B"];
However it's the same as working with
Dictionary<string, int> intDict = new Dictionary<string, int>();
So the MyRepository class may be edited to use Dictionary<string, T> instead of MyDictionary<T>.
#Konstantin's answer made me remember that there is actually a very fast lookup method - array indexing. This crude PoC code shows a variant of the required structure.
public class TypeDictionary {
static int _maxId = 0;
int _id;
static class Store<T>{
internal static List<T> Values = new List<T>();
}
public TypeDictionary() {
_id = _maxId++;
}
public T GetValue<T>() {
return Store<T>.Values[_id];
}
public void SetValue<T>(T value) {
while(Store<T>.Values.Count < _id) {
Store<T>.Values.Add(default(T));
}
Store<T>.Values[_id] = value;
}
}
This code can be used as follows:
var dict1 = new TypeDictionary();
dict1.SetValue("my string");
string result = dict1.GetValue<string>();
The problem with this solution is it's memory usage caused by the repository being not sparse. This also makes first time value setting more expensive.
Try this:
public class MyDictionary
{
List<object> values;
public MyDictionary()
{
values = new List<object>();
}
public T GetValue<T>()
{
return values.OfType<T>().FirstOrDefault();
}
public bool Add<T>(T value)
{
if (values.OfType<T>().Any())
return false;
else
{
values.Add(value);
return true;
}
}
}
and use it:
var md = new MyDictionary();
md.Add("!!!");
string s = md.GetValue<string>();
This class may store up to one value of type T. But there could corner cases with derived classes and interfaces I guess. You may check, if it suits your need, and probably modify it as you need, if it's close to what you need in general.
What you are looking for is impossible in C#. The language does not support a container that could store multiple objects of different types yet provides a look up method that does not involve casting, boxing or unboxing. You could accomplish something like this with macros in C++, or via a language like javascript where the structure of types can be changed at run-time.
The usage case you are describing fits quite closely with the purpose for which ConditionalWeakTable<TKey,TValue> was added to .NET 4.0. For the purpose you describe, you would include such a table in a static generic class, and then for every class object that's supposed to contain a reference to an item of a particular type you would store into that type's table a reference to object that's supposed to contain the item along with either a reference to the item, or else a reference to a simple item-holder object (note that entries in ConditionalWeakTable will evaporate when an object ceases to exist, but are otherwise immutable, so if you want a mutable association you'll need to create an object to hold it).
Building on #phoog's example with #supercat's suggestion
public class TypeDict
{
public T Get<T>() where T : class
{
T value;
InnerDict<T>.Values.TryGetValue(this, out value);
return value;
}
public void Set<T>(T value) where T : class
{
var cwt = InnerDict<T>.Values;
// lock+remove+add https://github.com/dotnet/coreclr/issues/4545
lock (cwt)
{
cwt.Remove(this);
cwt.Add(this, value);
}
}
private static class InnerDict<T> where T : class
{
public static ConditionalWeakTable<TypeDict, T> Values { get; private set; }
static InnerDict()
{
Values = new ConditionalWeakTable<TypeDict, T>();
}
}
}

C# Return an object from a list based on index

I need to make some changes so that I only retrieve one object at a time from my list instead of the entire list as I do now.
Right now ive got a private list in class B with a property returning the entire list basically making it public anyway and I want to change this.
The way class a looks(the ui class operating with the list) is, I enter some data validate it and send it to class B which in turn packages it into a list of objects based on the input.
Then class A needs to loop this list and add it to a listview for displaying it which looks like this at the moment:
ListViewItem lvi = new ListViewItem();
foreach ([Object] o in CLassB.getList())
{
lvi = new ListViewItem(o.property0);
lvi.SubItems.Add(o.property1);
lvi.SubItems.Add(o.property2);
lvi.SubItems.Add(o.property3);
}
}
Object is my abstract class which controls how the different types of items are added and getList() is my method in class B returning the entire list.
The thing is these propertys are the common ones all classes share the there are some that arent, like a textbox that you enter specific text about the object and so on which is displayed like this:
private void lvRegistered_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (Listview.SelectedItems.Count > 0)
{
foreach ([Object] ob in ClassB.getList())
{
if (Listview.SelectedItems[0].SubItems[0].Text == ob.id.ToString())
{
TextBox.Clear();
TextBox.Text = ob.property4;
}
}
}
}
Now this all works great at the moment but now I have a returned list to operate on but I dont want to return the list making it public I want to return one object of the list based on an index number (yes the functionality will be exactly the same, I made a method returning the count of the private list so I can loop over it and return all). This is for practicing OOP for when I dont want to return everything.
How would this be done? All I can think of is making a new list, take an int as input and search my private list and find the index then add that to the other list and return that list, but I dont know if this is good practice or the best way to do it? Well I havent looked into how to "copy" one element over to next list either but might aswell check and see if theres a better way to do things?
Just get the feeling im "taking the long way around" this way
Not sure to understand, but how about a simple GetById method?
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Test
{
private List<Foo> list = new List<Foo>();
public void Add(Foo foo)
{
this.list.Add(foo);
}
public Foo GetById(int id)
{
return this.list.FirstOrDefault(z => z.Id == id);
}
}
....
Test test = new Test();
test.Add(new Foo { Id = 1, Name = "1" });
test.Add(new Foo { Id = 2, Name = "2" });
test.Add(new Foo { Id = 3, Name = "3" });
Foo foo2 = test.GetById(2);
I'm not sure I understand completely, but it sounds like you could resolve this be creating an indexer on class B to return the item you want:
public object this[int index] {
get {
return list[index];
}
}
change 'object' to whatever your class type actually is.
You can then access the items as if class B was an array:
object item = classB[5];
1) You can use List.AsReadOnly() Method.
public ReadOnlyCollection<Double> MyList {
get {
return myList.AsReadOnly();
}
}
private List<Double> myList;
2) Use index method in the class.
public Double this[int index] {
get {
return myList[index];
}
set {
myList[index] = value;
}
}
private List<Double> myList;
Did about the same as suggested by Ken2k but instead I went with this:
public [Class] getListItem(int index)
{
return myList.ElementAt(id);
}
which in turn is used in my other class that displays the info like:
for (int i = 0; i < am.getCount(); i++)
{
ListViewItem = new ListViewItem([class reference].getList(i).[property].ToString());
ListViewItems.SubItems.Add([class reference].getList(i).[property]);
}
Thanks everyone for all your help on this.

Categories