I have a class A which holds a collection of objects. Every instance of the class fills the collection according a different logic. From time to time I need to update all the collections.
I was thinking this could be done maybe if the class has a method that holds the logic for filling the collection and I can set this logic at the time of the creation of the object.
Like this:
MyClass instance = new MyClass();
instance.updateCollection = { logic for filling the collection } //
The logic will be different for each object.
Thanks
You can achieve this easily with an Action.
Either pass yor desired Action in the constructor, or make a property that allows you to set the desired Action.
Sounds like you should be using something like a Factory which creates these objects, but stores a reference to them as well. You can then have a separate method inside your factory to update each collection inside the factory.
Also - don't constrain yourself to one class. If you embrace the ideas of polymorphism and inheritance instead of fighting them, you'll find C# a lot easier and more fun.
Here is an example using Action class:
class MyClass
{
private readonly Action<List<string>> _updateAction;
private readonly List<string> _collection = new List<string>();
public MyClass(Action<List<string>> updateAction)
{
_updateAction = updateAction;
}
public void Update()
{
_updateAction(_collection);
}
}
class MyClassTester
{
public static void Test()
{
MyClass weekdayAdder = new MyClass(c => c.Add(DateTime.Now.DayOfWeek.ToString()));
MyClass timeAdder = new MyClass((c) => c.Add(DateTime.Now.ToShortTimeString()));
weekdayAdder.Update();
weekdayAdder.Update();
timeAdder.Update();
timeAdder.Update();
timeAdder.Update();
}
}
Related
So I've been working with classes with single instances in Unity for a while and generally do this:
class PublicThings {
public static PublicThings I; // instance of this class
public int Score;
void Start { I = GetComponent<PublicThings>(); }
}
Usage: PublicThings.I.Score = 10;
Which works pretty well. However, I've been curious as to whether or not it's possible to have the instance of the class be returned without having to type .I after the class.
So basically here's how it would look instead:
PublicThings.Score = 10;
This question seems like it's relevent but I'm having trouble getting it to work.
Is this possible? If so, how would it be done?
Three options to do what you are looking to do:
Make a static property/field with the static keyword in the PublicThings class
Make a ScriptableObject and attach it to the item that is calling it (video tutorial)
Utilize the Singleton Pattern (I would suggest avoid using this method before trying the other two)
Also it's worth noting that the Singleton Pattern doesn't necessarily solve your problem. You will still have to call something like PublicThings.instance.Score.
Hope this helps.
Singleton pattern is the way to go.
Also, with lazy instantiation.
public class PublicThings
{
private static PublicThings _instance;
// Your private constructor
private PublicThings() { }
public static PublicThings Instance
{
get
{
if (_instance == null)
{
// Construction of instance logic here
_instance = new PublicThings();
}
return _instance;
}
// No setter, read-only property
}
// Decide if Score is a read-only property or not.
public int Score { get; set; }
}
Whener the single instance of PublicThings is required, it will be constructed and then stored. A second access to the instance will provide the stored one.
[Test]
public void WithTwoAccess_ToSingleInstance_MustBeTheSame()
{
var things1 = PublicThings.Instance;
var things2 = PublicThings.Instance;
Assert.AreSame(things2, things1);
// Asserts true
}
If your Score property must be set once, just change que Instance property to a method (commonly called GetInstance) which expects the value of Score.
Hope it helps.
I got something like the following:
class Factory{
private List<FactorizableObject> _collected; //Collection of all created objects
public FactorizableObject createObject (someParams DontMatter){
FactorizableObject newObject = new FactorizableObject(DontMatter);
_collected.Add(newObject);
return newObject;
}
public void DoSomethingWithCollectedObjects(){
//Work with created objects
}
}
class UsingClass1{
private FactorizableObject myObject;
public UsingClass1(){
myObject = Factory.createObject(someParams);
}
}
class UsingClass2{
private FactorizableObject myObject;
public UsingClass2(){
myObject = Factory.createObject(someOtherParams);
}
}
class WorkingClass{
List<UsingClass1> someOfThese;
List<UsingClass2> someOfThose;
private void triggerWork(){
someOfThese.Remove(RemoveSomeObject);
Factory.DoSomethingWithCollectedObjects();
}
}
Now my Problem is: Even if I remove an instance of a usingClass from on of these lists, the entries in the factory still keep alive and get used when calling DoSomethingWithCollectedObjects. I expected something like a NullreferenceException when trying to work on the object.
The Question: Is there a way to kill the object (the reference to the object) without explicit removing it from the factory-collection? This would need to be done in any class using the factory, so I would like to get around this...
I need some collection like this to perform some special actions on the factorized objects and dont want to care where they are located (The action needs to be done on ALL of the objects). I already tried setting UsingClass1.myObject = null, before removing the object, but this only removed my reference onto the factorized object.
I've been searching for awhile to see if anyone was trying to do something close to this and I find a bunch of people trying to interact with a generically typed List. I instead need to interact with a List of complex objects who are generically typed. Here's the current code.
public class RequestBundleItem<T> where T : BaseJsonResponseMessage
{
public T Response { get; private set; }
//intializers - code not needed
public void SetResponse(String jsonResponse)
{
Response = (T)jsonResponse.JsonToObject<T>();
}
}
public class RequestBundleManager
{
private List<RequestBundleItem<T>> BundleItems;
public async Task<List<RequestBundleItem<T>>> ProcessItemsAsync()
{
List<Task<JsonValueEventArgs>> tasks = //create tasks from bundleitems;
for (var i = 0; i < tasks.Count(); i++)
{
Task<JsonValueEventArgs> curTask = tasks[i];
var args = await curTask;
BundleItems[i].SetResponse(args.ValueAsText);
}
return BundleItems;
}
public void AddItem<T>(RequestBundleItem<T> newItem) where T : BaseJsonResponseMessage
{
BundleItems.Add(newItem);
}
}
This line is what's causing the problem
private List<RequestBundleItem<T>> BundleItems;
I don't know how to define this list since T is generic and just needs to implement BaseJsonResponseMessage but I don't want to type the RequestBundleManager itself.
SOLUTION:
I ended up removing the generic from the RequestBundleItem and the consumer is responsible for knowing the response type it needs back.
Make RequestBundleManager generic also:
public class RequestBundleManager<T>
And now you list can be defined with type T. Of course, you have to make sure that the T you use when creating your RequestBundleManger is the same as the one you used for RequestBundleItem, and you list will be homogeneous.
If you want your RequestBundleManager to handle lists with mixed T, then you will need to have RequestBundleItem derive from a base class or else have it implement an interface.
Define the list in your RequestBundleManager like this:
private List<RequestBundleItem<BaseJsonResponseMessage>>
If you don't put a type on the RequestBundleManager, you don't know the specific type of the object inside the list except that it's a BaseJsonResponseMessage. Then it makes sense to just define it like that. It will give you access only to methods defined in BaseJsonResponseMessage though.
If that's not enough, consider defining an interface with all the methods you want to have access to in the RequestBundleManager and put it as a constraint on your type in RequestBundleItem. Something like this:
public class RequestBundleItem<T> where T : BaseJsonResponseMessage, IMyInterface
Then define the list in RequestBundleManager like:
private List<RequestBundleItem<IMyInterface>>
Say I have a class with a number of methods - some private, some public.
In one of the public methods, I create a list of objects. This is then used across a number of other methods, which have simply been abstracted out to make code simpler.
So I might have:
public class MyClass
{
public void CreateList()
{
List<MyClass> MyList = new List<MyClass>();
... populate list
DedupeList();
ValidateList();
}
void DedupeList()
{
// do something using MyList
}
void ValidateList()
{
// do something using MyList
}
}
I was wondering what the best approach would be in this instance.
Make the list created by CreateList() a class level variable;
Pass the list a parameter to each of the sub-methods.
Ok, so it depends on what you're trying to achieve and what your classes responsibility is.
If you class represents a real thing which represents part of your domain, and which has state, then your private methods act on that state and I would therefore choose the former.
So
public class Basket
{
private IList<string> Contents;
public Basket()
{
Contents = new Contents();
}
public void Add(string Item)
{
Contents.Add(Item);
}
public void Empty()
{
Contents.Clear();
}
}
This is a trite example, but all I could think of.
If however your class doesn't represent an object with state, such as the calculator below which takes some input, acts on it, and returns it without storing anything, then the latter is better.
That said, there are other considerations, such as keeping code clean and easy to read (should be very high on your priority list), limiting the number of parameters etc being passed (any more than three is often regarded as messy). Example below of when I would elect to pass parameters.
public class InvestmentCalculator
{
pubilc IEnumerable<Stock> CalculateInvestmentValue(IEnumerable<Stock> Stocks)
{
foreach (var stock in stocks)
{
var itemValue = GetSotckValueFromMarket(stock);
stock.UpdateValue(itemValue)
AddProjection(stock);
}
}
public decimal GetStockValueFromMarket(Stock stock)
{
//Do something
}
public decimal AddProjection(Stock stock)
{
//Do something
}
}
I hope that this helps
It depends on meaning of the list. You have to find some answers. Should it be a part of the class or just a temporary variable that should live just along the method call? Is it a part of behavior of the class? How about threading? Even you may rethink if DedupeList and ValidateList methods have to be part of this class or do they deserve a separate class?
I recommend you to read "Implementation Patterns" by Kent Beck and "Clean Code" by Robert C. Martin. There are dozens of very helpful tips for these kind of little but frequent cases.
Context: this is based on a question that was asked and then deleted before I could answer it - but I think it is a good question, so I've tidied it, rephrased it, and re-posted it.
In a high-throughput scenario using protobuf-net, where lots of allocations are a problem (in particular for GC), is it possible to re-use objects? For example by adding a Clear() method?
[ProtoContract]
public class MyDTO
{
[ProtoMember(1)]
public int Foo { get; set; }
[ProtoMember(2)]
public string Bar { get; set; }
[ProtoMember(3, DataFormat = DataFormat.Group)]
public List<int> Values { get { return values; } }
private readonly List<int> values = new List<int>();
public void Clear()
{
values.Clear();
Foo = 0;
Bar = null;
}
}
protobuf-net will never call your Clear() method itself, but for simple cases you can simply do this yourself, and use the Merge method (on the v1 API, or just pass the object into Deserialize in the v2 API). For example:
MyDTO obj = new MyDTO();
for(...) {
obj.Clear();
Serializer.Merge(obj, source);
}
This loads the data into the existing obj rather than creating a new object each time.
In more complex scenarios where you want to reduce the number of object allocations, and are happy to handle the object pooling / re-use yourself, then you can use a custom factory. For example, you can add a method to MyDTO such as:
// this can also accept serialization-context parameters if
// you want to pass your pool in, etc
public static MyDTO Create()
{
// try to get from the pool; only allocate new obj if necessary
return SomePool.GetMyDTO() ?? new MyDTO();
}
and, at app-startup, configure protobuf-net to know about it:
RuntimeTypeModel.Default[typeof(MyDTO)].SetFactory("Create");
(SetFactory can also accept a MethodInfo - useful if the factory method is not declared inside the type in question)
With this, what should happen is the factory method is used instead of the usual construction mechanisms. It remains, however, entirely your job to cleanse (Clear()) the objects when you are finished with them, and to return them to your pool. What is particularly nice about the factory approach is that it will work for new sub-items in lists, etc, which you can't do just from Merge.