On reflection, I'm wondering if my implementation is incorrect. Specifically if my subscriber method Cooler.OnTemperatureChanged's parameters are wrong. It just seems a little... bulky to me. Like I'm not adhering to encapsulation properly by the subscriber requiring knowledge of Thermostat.TemperatureArgs subclass. I suppose I can move the TemperatureArgs class outside of the Thermostat class and that's fine...?
Anyway if someone could sanity check me it'd be much appreciated. Trying to get my brain back into OO mode is harder than I thought!
using System;
namespace ConsoleApplication1
{
public class Thermostat
{
public class TemperatureArgs : System.EventArgs
{
public float NewTemperature;
public TemperatureArgs( float newTemperature )
{
NewTemperature = newTemperature;
}
}
public event EventHandler<TemperatureArgs> OnTemperatureChange = delegate { };
public float CurrentTemperature
{
get { return _CurrentTemperature; }
set
{
if (value != CurrentTemperature)
{
_CurrentTemperature = value;
Console.WriteLine($"Temperature set to {value}");
OnTemperatureChange?.Invoke(this, new TemperatureArgs(value));
}
}
}
private float _CurrentTemperature;
}
class Cooler
{
public Cooler(float temperature)
{
Temperature = temperature;
}
public float Temperature { get; set; }
public void OnTemperatureChanged(object sender, Thermostat.TemperatureArgs tempArgs)
{
if (tempArgs.NewTemperature > Temperature)
{
System.Console.WriteLine("Cooler: On");
}
else
{
System.Console.WriteLine("Cooler: Off");
}
}
}
static class Program
{
static void Main(string[] args)
{
Thermostat thermostat = new Thermostat();
Cooler cooler = new Cooler(80);
thermostat.OnTemperatureChange += cooler.OnTemperatureChanged;
Console.Write("Enter new temperature: ");
string temperature = Console.ReadLine();
thermostat.CurrentTemperature = int.Parse(temperature);
Console.Read(); //Pause and reflect a moment...
}
}
}
You know those moments when you call someone over to ask about why something isn't working and then the moment you start explaining it to them you figure that shit out on your own.
I just had the same thing but with a really long post here.
So basically what I'm saying is thanks guys, you solved my problem by just existing!
Also C# events are not as simple as I would have expected!
One thing I see that is apparently pretty rare is to use Funcs instead of bothering with setting up FooArgs for a delegate. Always felt really verbose to me to declare a separate type for a delegate signature when you can use a Func<foo, bar> and have it generic instead.
0
Options
KakodaimonosCode fondlerHelping the 1% get richerRegistered Userregular
This... is not what I meant when I said we needed to fix the keys in the dictionary to not use doubles.
public class MyDictionaryBecauseImStupid<TKey, TValue> : IDictionary<TKey, TValue>
{
private Dictionary<double, TValue> backingDictionary;
public void Add(TKey key, TValue value)
{
double roundedKey = 0.0;
Type objType = key.GetType();
objType = Nullable.GetUnderlyingType(objType) ?? objType;
if (objType.IsPrimitive)
{
if (objType == typeof(double) || objType == typeof(float))
{
double tempKey;
if(double.TryParse(key.ToString(), out tempKey))
{
roundedKey = Math.Round(tempKey, 2);
backingDictionary.Add(roundedKey, value);
}
}
}
}
}
Could you explain more @Echo? Do you mean using an Action/Func delegate instead of the event, or somehow using them as part of the event code? I'm trying to refactor to do the latter, but not having much success!
You know those moments when you call someone over to ask about why something isn't working and then the moment you start explaining it to them you figure that shit out on your own.
I just had the same thing but with a really long post here.
So basically what I'm saying is thanks guys, you solved my problem by just existing!
Also C# events are not as simple as I would have expected!
Just serve a page that says "The stone age called, they want their phone back."
Pretty close -- we just the text "Browser upgrade required" and nothing else if we know for sure it won't work. If we detect something that will still work, but might look a bit crooked in places, we show "Browser upgrade recommended", so that users at least know to expect weirdnesses.
Is it:
1. Opaque purple-y blue?
or
2. Semi-transparent light cyan?
Answer: it depends, because WPF does ARGB and CSS does RGBA, and it took me an annoyingly long time to realise that. It doesn't help that both those colours above are "blue-ish" so both of them seemed like plausible fits for what I was seeing on screen with all the other things next to/behind/in front of it.
Could you explain more @Echo? Do you mean using an Action/Func delegate instead of the event, or somehow using them as part of the event code? I'm trying to refactor to do the latter, but not having much success!
I suppose I was speaking more about delegates than events, but since you use delegates for events... As you say, it can get really bulky. I think it's a remnant from older .NET versions where you had to do it that way, but you can get rid of a lot of that with generic Funcs now.
I don't have time for a full explanation atm, but I did remember I had this old silly but somewhat relevant example from when I did some tutoring.
You have a bunch of cars in a race that might explode if they go too fast. Car class looks like this:
using System;
namespace EventsDemo
{
class Car
{
static Random random = new Random();
public event Action<Car> Accelerate;
public event Action<Car> Explode;
public int Position { get; set; }
public string Make { get; set; }
public bool IsExploded { get; set; }
public void Drive()
{
var speed = random.Next(10, 100) + 1;
if (speed > 90)
{
IsExploded = true;
Explode?.Invoke(this);
}
else
{
Position += speed;
Accelerate?.Invoke(this);
}
}
public override string ToString()
{
return $"{Make} at pos {Position}, exploded: {IsExploded}";
}
}
}
And then this is the main race bit:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace EventsDemo
{
class Program
{
private const int RaceLength = 300;
private static Car winner = null;
static void Main(string[] args)
{
var cars = new List<Car>
{
new Car {Make = "Lotus"},
new Car {Make = "Volvo"},
new Car {Make = "Koenigsegg"}
};
// Register events before race
foreach (Car car in cars)
{
car.Explode += Car_Explode;
car.Accelerate += Car_Accelerate;
}
do
{
foreach (Car car in cars)
{
if (!car.IsExploded)
{
car.Drive();
}
if (winner == null && car.Position >= RaceLength)
{
winner = car;
}
//Console.WriteLine(car);
}
Console.WriteLine();
Thread.Sleep(1000);
} while (cars.Any(c => !c.IsExploded && c.Position < RaceLength));
// Race completed
if (winner != null)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Winner: {winner.Make}!");
Console.ResetColor();
}
else
{
Console.WriteLine("All cars went kaboom!");
}
}
private static void Car_Accelerate(Car car)
{
Console.WriteLine($"{car.Make} accelerated to {car.Position}");
}
private static void Car_Explode(Car car)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"BOOM! {car.Make} exploded at {car.Position}!");
Console.ResetColor();
}
}
}
I'm simply using an Action<Car> instead of the whole song and dance routine with writing EventHandler stuff.
Here's a quick refactor to use an Action<float> instead of an EventHandler. Advantage of doing it this way is that there's no longer any TemperatureArgs the subscriber needs to know about, just send the new temperature.
edit: got the Action down to one argument.
using System;
namespace ConsoleApplication1
{
public class Thermostat
{
public event Action<float> OnTemperatureChange;
public float CurrentTemperature
{
get { return _CurrentTemperature; }
set
{
if (value != CurrentTemperature)
{
_CurrentTemperature = value;
Console.WriteLine($"Temperature set to {value}");
OnTemperatureChange?.Invoke(value);
}
}
}
private float _CurrentTemperature;
}
class Cooler
{
public Cooler(float temperature)
{
Temperature = temperature;
}
public float Temperature { get; set; }
public void OnTemperatureChanged(float value)
{
if (value > Temperature)
{
System.Console.WriteLine("Cooler: On");
}
else
{
System.Console.WriteLine("Cooler: Off");
}
}
}
static class Program
{
static void Main(string[] args)
{
Thermostat thermostat = new Thermostat();
Cooler cooler = new Cooler(80);
thermostat.OnTemperatureChange += cooler.OnTemperatureChanged;
Console.Write("Enter new temperature: ");
string temperature = Console.ReadLine();
thermostat.CurrentTemperature = int.Parse(temperature);
Console.Read(); //Pause and reflect a moment...
}
}
}
Thanks for the update Echo, I see what you mean now. Interestingly the book initially taught this method, but with a change of
public event Action<float> OnTemperatureChange;
to
public Action<float> OnTemperatureChange;
Strangely (at least I think), this still works fine. Action being quite happy to be used even as a multicast delegate with as many listeners as you want.
The book speaks of a few disadvantages, but most are only relevant to the latter declaration. Those being allowing the = operator when adding listeners (thus resetting the list and getting rid of any listeners you've already added, ouch!) and allowing the direct invocation of the event function (you could call thermostat.OnTemperatureChange(666) directly for example).
I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.
Take all of this with a grain of salt, I'm literally talking about what I've learned over the last 24 hours >_<
I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.
You can also pass along the object itself in the Invoke call, like I do in the Car class in my example.
I actually did this to myself, sorta. A few months back I created some documentation for how to restart the modem here in the office, because there are a few similar looking devices back there, and I didn't want people accidentally unplugging the modem that the security system uses to dial out, or whatever that other box is.
Internet went out yesterday. Needed to restart modem. Let me just check the...
...
+5
Options
GnomeTankWhat the what?Portland, OregonRegistered Userregular
Thanks for the update Echo, I see what you mean now. Interestingly the book initially taught this method, but with a change of
public event Action<float> OnTemperatureChange;
to
public Action<float> OnTemperatureChange;
Strangely (at least I think), this still works fine. Action being quite happy to be used even as a multicast delegate with as many listeners as you want.
The book speaks of a few disadvantages, but most are only relevant to the latter declaration. Those being allowing the = operator when adding listeners (thus resetting the list and getting rid of any listeners you've already added, ouch!) and allowing the direct invocation of the event function (you could call thermostat.OnTemperatureChange(666) directly for example).
I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.
Take all of this with a grain of salt, I'm literally talking about what I've learned over the last 24 hours >_<
What book are you reading that suggests those first two things are equivalent, or that the second one is in any way multicast? The second declaration can only ever have one function assigned to that variable, it's not multicast in the slightest. This book seems to be doing you a major disservice by conflating events and delegates. While events are implemented using delegates, they are not the same thing. For your stated purpose you should absolutely being using an event. Whether you want to follow convention and use TEventArgs with EventHandler<T> is up to you, but you definitely should be using the event keyword.
GnomeTankWhat the what?Portland, OregonRegistered Userregular
edited March 2017
So I just broke my work laptop screen, woo. The ThinkPad's they give us at work are totally shite. I had my MacBook sitting on top of it, and the MacBook started to fall. I caught it, but it swung back and made relatively minor contact with the lid of my ThinkPad....caused a complete crack in it and broke the LCD screen. Now I see why: The plastic of the lid is so thin it's comical.
You know those moments when you call someone over to ask about why something isn't working and then the moment you start explaining it to them you figure that shit out on your own.
I just had the same thing but with a really long post here.
So basically what I'm saying is thanks guys, you solved my problem by just existing!
Also C# events are not as simple as I would have expected!
This is one reason why I always wrote emails instead of asking in person (that and I'm awful at remembering stuff I hear vs read) -- half the time I figure out the answer or another approach before I finish the email.
Thanks for the update Echo, I see what you mean now. Interestingly the book initially taught this method, but with a change of
public event Action<float> OnTemperatureChange;
to
public Action<float> OnTemperatureChange;
Strangely (at least I think), this still works fine. Action being quite happy to be used even as a multicast delegate with as many listeners as you want.
The book speaks of a few disadvantages, but most are only relevant to the latter declaration. Those being allowing the = operator when adding listeners (thus resetting the list and getting rid of any listeners you've already added, ouch!) and allowing the direct invocation of the event function (you could call thermostat.OnTemperatureChange(666) directly for example).
I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.
Take all of this with a grain of salt, I'm literally talking about what I've learned over the last 24 hours >_<
What book are you reading that suggests those first two things are equivalent, or that the second one is in any way multicast? The second declaration can only ever have one function assigned to that variable, it's not multicast in the slightest. This book seems to be doing you a major disservice by conflating events and delegates. While events are implemented using delegates, they are not the same thing. For your stated purpose you should absolutely being using an event. Whether you want to follow convention and use TEventArgs with EventHandler<T> is up to you, but you definitely should be using the event keyword.
It's Essential C# 6.0 5th edition by Mark Michaelis and Eric Lippert.
Perhaps I'm misunderstanding the terminology of multicast. I was definitely able to add multiple listeners using OnTemperatureChange without declaring it as an event, is this all that is meant by multicast or is there more involved? I agree it does seem really odd that this works! The code below gives the correct (as far as I can figure) output.
You can add as many cooler/heaters as you like and it still seems to work. The book even had me messing around with inserting a delegate function via a lambda which threw an exception to show how to handle such things.
output:
Enter new temperature: 100
Temperature set to 100
Cooler: On
Heater: Off
I just realised I should probably stop shitting up the thread with massive reams of code, so it's spoilered...
using System;
namespace ConsoleApplication1
{
public static class ThermostatTestings
{
public static void ThermostatTest()
{
Thermostat thermostat = new Thermostat();
Cooler cooler = new Cooler(80);
Heater heater = new Heater(50);
thermostat.OnTemperatureChange += cooler.OnTemperatureChanged;
thermostat.OnTemperatureChange += heater.OnTemperatureChanged;
Console.Write("Enter new temperature: ");
string temperature = Console.ReadLine();
thermostat.CurrentTemperature = int.Parse(temperature);
}
}
public class Thermostat
{
public Action<float> OnTemperatureChange;
public float CurrentTemperature
{
get { return _CurrentTemperature; }
set
{
if (value != CurrentTemperature)
{
_CurrentTemperature = value;
Console.WriteLine($"Temperature set to {value}");
OnTemperatureChange?.Invoke( value );
}
}
}
private float _CurrentTemperature;
}
class Cooler
{
public Cooler(float temperature)
{
Temperature = temperature;
}
public float Temperature { get; set; }
public void OnTemperatureChanged(float NewTemperature)
{
if (NewTemperature > Temperature)
{
System.Console.WriteLine("Cooler: On");
}
else
{
System.Console.WriteLine("Cooler: Off");
}
}
}
class Heater
{
public Heater(float temperature)
{
Temperature = temperature;
}
public float Temperature { get; set; }
public void OnTemperatureChanged(float NewTemperature)
{
if (NewTemperature < Temperature)
{
System.Console.WriteLine("Heater: On");
}
else
{
System.Console.WriteLine("Heater: Off");
}
}
}
}
GnomeTankWhat the what?Portland, OregonRegistered Userregular
And then someone comes along and does thermostat.OnTemperatureChange = Handler, or worse yet thermostat.OnTemperatureChange = null, and you lose all the others. Plus this is relying on an implementation detail of CLR delegates, which is that they can have multiple handlers attached to them in the empty state, and implementation detail you are not supposed to rely on and could go away at any time. It's bad C#, and the fact that a book is teaching it to you as "a good way to do things" is frustrating.
Would a good way to work with classes and to do some more complex algorithm type stuff be to make classes based on everyday objects/activities I use/do?
Would a good way to work with classes and to do some more complex algorithm type stuff be to make classes based on everyday objects/activities I use/do?
It can be instructive but not necessarily lead to the best designs. Here's an example that illustrates it pretty well. The author proposes a design problem (structure a coffee machine design that can do some stuff) then shows how a design that reflects the physical object doesn't quite capture the right abstractions to allow for a clean design.
And then someone comes along and does thermostat.OnTemperatureChange = Handler, or worse yet thermostat.OnTemperatureChange = null, and you lose all the others. Plus this is relying on an implementation detail of CLR delegates, which is that they can have multiple handlers attached to them in the empty state, and implementation detail you are not supposed to rely on and could go away at any time. It's bad C#, and the fact that a book is teaching it to you as "a good way to do things" is frustrating.
Interestingly enough the book even states these problems before going onto teaching the proper events methodology. Quite why it bothered I'm not sure... I will most certainly be using events for all such things!
Thanks for all the feedback chaps, being back in OO feels great!
jaziekBad at everythingAnd mad about it.Registered Userregular
We're starting a new project at work to write a CRM which integrates with all our other products.
Why we're doing this and not just making integration modules for the big name CRMs that are way better than anything we could do I don't know, but whatever.
Having said that, it's a cool opportunity to play with some new frameworks and such. We're going with Vue for the front end, and while I'm not really one for JS if I can help it, vue looks surprisingly palatable.
I'm working on a roles based permission system. In this application there are users and users have many different types of private resources that they can CRUD.
Some users with a certain role will have permission to view other users resources. The problem is I need to provide fine-grained control over which user's resources they will be allowed to view and which ones they will be blocked from viewing.
Is there a pattern for implementing such a system without having to explicitly specify all the user IDs per resource that role is allowed to access? There could be hundreds of users and dozens of roles...
In some cases a role could be restricted to seeing only a handful of users, and in others it might be able to see every user except for a few.
I was thinking about creating per resource one boolean value that specifies if that role can see everyone by default, and then creating a list of user IDs to include or exclude per resource.
I'm working on a roles based permission system. In this application there are users and users have many different types of private resources that they can CRUD.
Some users with a certain role will have permission to view other users resources. The problem is I need to provide fine-grained control over which user's resources they will be allowed to view and which ones they will be blocked from viewing.
Is there a pattern for implementing such a system without having to explicitly specify all the user IDs per resource that role is allowed to access? There could be hundreds of users and dozens of roles...
In some cases a role could be restricted to seeing only a handful of users, and in others it might be able to see every user except for a few.
I was thinking about creating per resource one boolean value that specifies if that role can see everyone by default, and then creating a list of user IDs to include or exclude per resource.
Maybe this concept has a name?
You're building a security system? There's a ton of potential solutions out there for this. I know for our system we have a reference table of available resources, and they get some or all of them as rights in a copied version that the program checks on login/render every time to determine what they have access to.
I can talk more detail if you can give some more concrete examples.
Key concepts to think about: Are new resources going to be centrally added or just pop in all the time created by users? What's the timing needed between change to resource rights and when it needs to happen (is it immediate or within a few minutes?)? What high-level role frameworks do you expect to have (IE Security Admin, Security Worker, User, Super User etc.)? What's the rate of change?
Generally I think you want to store resource rights with a user rather than vice versa, as then you have more options around master user control instead of master resource control (IE - someone gets fired it's much easier to just shut down a centralized master user record that's the reference for all other rights)
Is this a "people own stuff but some people are helpers that need to see everything except in sensitive cases then only a few can" type thing?
I'm working on a roles based permission system. In this application there are users and users have many different types of private resources that they can CRUD.
Some users with a certain role will have permission to view other users resources. The problem is I need to provide fine-grained control over which user's resources they will be allowed to view and which ones they will be blocked from viewing.
Is there a pattern for implementing such a system without having to explicitly specify all the user IDs per resource that role is allowed to access? There could be hundreds of users and dozens of roles...
In some cases a role could be restricted to seeing only a handful of users, and in others it might be able to see every user except for a few.
I was thinking about creating per resource one boolean value that specifies if that role can see everyone by default, and then creating a list of user IDs to include or exclude per resource.
Maybe this concept has a name?
You're building a security system? There's a ton of potential solutions out there for this. I know for our system we have a reference table of available resources, and they get some or all of them as rights in a copied version that the program checks on login/render every time to determine what they have access to.
I can talk more detail if you can give some more concrete examples.
Key concepts to think about: Are new resources going to be centrally added or just pop in all the time created by users? What's the timing needed between change to resource rights and when it needs to happen (is it immediate or within a few minutes?)? What high-level role frameworks do you expect to have (IE Security Admin, Security Worker, User, Super User etc.)? What's the rate of change?
Generally I think you want to store resource rights with a user rather than vice versa, as then you have more options around master user control instead of master resource control (IE - someone gets fired it's much easier to just shut down a centralized master user record that's the reference for all other rights)
Is this a "people own stuff but some people are helpers that need to see everything except in sensitive cases then only a few can" type thing?
To answer:
-New resources are popping in all the time created by users.
-Changes to rights happen immediately
-Most of the roles are not really IT type of roles, rather they are more like organizational and company type roles.
-Rate of change, once a role is defined it usually doesn't need to change.
I could store resource rights with a user, but then it makes it a cumbersome experience when you have for example a "Service Department" role with 10 users and they all need the same level of access to certain resources of a subset of users.
If someone is fired there is a user record in the database that could simply have a disabled flag set that would prevent them from logging in or using any API routes.
It is a "people own stuff but some people are helpers that need to see everything except in sensitive cases then only a few can" type of thing.
I already have a roles system implemented that allows for fine-grain control of what users can and can't do based on activities. Resource access though is still a harder problem to design for because of the variable amount of users over time.
Posts
Anyway if someone could sanity check me it'd be much appreciated. Trying to get my brain back into OO mode is harder than I thought!
http://steamcommunity.com/id/pablocampy
Yeah I can't tell you how many times I wrote out a long ass post only to delete all the text because I figured it out.
This... is not what I meant when I said we needed to fix the keys in the dictionary to not use doubles.
Now my eye is twitching.
http://steamcommunity.com/id/pablocampy
My coworkers think I'm crazy because I have one at my desk.
Threading bugs are the worst.
Pretty close -- we just the text "Browser upgrade required" and nothing else if we know for sure it won't work. If we detect something that will still work, but might look a bit crooked in places, we show "Browser upgrade recommended", so that users at least know to expect weirdnesses.
Is it:
1. Opaque purple-y blue?
or
2. Semi-transparent light cyan?
Answer: it depends, because WPF does ARGB and CSS does RGBA, and it took me an annoyingly long time to realise that. It doesn't help that both those colours above are "blue-ish" so both of them seemed like plausible fits for what I was seeing on screen with all the other things next to/behind/in front of it.
I suppose I was speaking more about delegates than events, but since you use delegates for events... As you say, it can get really bulky. I think it's a remnant from older .NET versions where you had to do it that way, but you can get rid of a lot of that with generic Funcs now.
I don't have time for a full explanation atm, but I did remember I had this old silly but somewhat relevant example from when I did some tutoring.
You have a bunch of cars in a race that might explode if they go too fast. Car class looks like this:
And then this is the main race bit:
I'm simply using an Action<Car> instead of the whole song and dance routine with writing EventHandler stuff.
edit: got the Action down to one argument.
Then when I try to create a slide without that value I get:
But I have a field RIGHT ABOVE IT:
And that works just fine.
edit: I restarted my localhost and it works now. Must be an issue of cache or something.
The book speaks of a few disadvantages, but most are only relevant to the latter declaration. Those being allowing the = operator when adding listeners (thus resetting the list and getting rid of any listeners you've already added, ouch!) and allowing the direct invocation of the event function (you could call thermostat.OnTemperatureChange(666) directly for example).
I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.
Take all of this with a grain of salt, I'm literally talking about what I've learned over the last 24 hours >_<
http://steamcommunity.com/id/pablocampy
You can also pass along the object itself in the Invoke call, like I do in the Car class in my example.
something like that
I actually did this to myself, sorta. A few months back I created some documentation for how to restart the modem here in the office, because there are a few similar looking devices back there, and I didn't want people accidentally unplugging the modem that the security system uses to dial out, or whatever that other box is.
Internet went out yesterday. Needed to restart modem. Let me just check the...
...
What book are you reading that suggests those first two things are equivalent, or that the second one is in any way multicast? The second declaration can only ever have one function assigned to that variable, it's not multicast in the slightest. This book seems to be doing you a major disservice by conflating events and delegates. While events are implemented using delegates, they are not the same thing. For your stated purpose you should absolutely being using an event. Whether you want to follow convention and use TEventArgs with EventHandler<T> is up to you, but you definitely should be using the event keyword.
This is one reason why I always wrote emails instead of asking in person (that and I'm awful at remembering stuff I hear vs read) -- half the time I figure out the answer or another approach before I finish the email.
It's Essential C# 6.0 5th edition by Mark Michaelis and Eric Lippert.
Perhaps I'm misunderstanding the terminology of multicast. I was definitely able to add multiple listeners using OnTemperatureChange without declaring it as an event, is this all that is meant by multicast or is there more involved? I agree it does seem really odd that this works! The code below gives the correct (as far as I can figure) output.
You can add as many cooler/heaters as you like and it still seems to work. The book even had me messing around with inserting a delegate function via a lambda which threw an exception to show how to handle such things.
output:
I just realised I should probably stop shitting up the thread with massive reams of code, so it's spoilered...
http://steamcommunity.com/id/pablocampy
It can be instructive but not necessarily lead to the best designs. Here's an example that illustrates it pretty well. The author proposes a design problem (structure a coffee machine design that can do some stuff) then shows how a design that reflects the physical object doesn't quite capture the right abstractions to allow for a clean design.
http://heim.ifi.uio.no/~mmo/generic/papers/coffee/Coffee-1.html
It's remarkably similar to a section in Agile Patterns Principles and Practices in C# which is a book I'd highly recommend if you work in C#.
edit: whoops, forgot to include part 2 of the paper:
http://heim.ifi.uio.no/~mmo/generic/papers/coffee/Coffee-2.html
Interestingly enough the book even states these problems before going onto teaching the proper events methodology. Quite why it bothered I'm not sure... I will most certainly be using events for all such things!
Thanks for all the feedback chaps, being back in OO feels great!
http://steamcommunity.com/id/pablocampy
Why we're doing this and not just making integration modules for the big name CRMs that are way better than anything we could do I don't know, but whatever.
Having said that, it's a cool opportunity to play with some new frameworks and such. We're going with Vue for the front end, and while I'm not really one for JS if I can help it, vue looks surprisingly palatable.
I'm working on a roles based permission system. In this application there are users and users have many different types of private resources that they can CRUD.
Some users with a certain role will have permission to view other users resources. The problem is I need to provide fine-grained control over which user's resources they will be allowed to view and which ones they will be blocked from viewing.
Is there a pattern for implementing such a system without having to explicitly specify all the user IDs per resource that role is allowed to access? There could be hundreds of users and dozens of roles...
In some cases a role could be restricted to seeing only a handful of users, and in others it might be able to see every user except for a few.
I was thinking about creating per resource one boolean value that specifies if that role can see everyone by default, and then creating a list of user IDs to include or exclude per resource.
Maybe this concept has a name?
NASA free software catalogue!
https://docs.google.com/spreadsheets/d/1OLcAGbXhWIVcl5IziVpG0eKFJS3xi_Sac9kYMkRFvD8/edit?usp=sharing
You're building a security system? There's a ton of potential solutions out there for this. I know for our system we have a reference table of available resources, and they get some or all of them as rights in a copied version that the program checks on login/render every time to determine what they have access to.
I can talk more detail if you can give some more concrete examples.
Key concepts to think about: Are new resources going to be centrally added or just pop in all the time created by users? What's the timing needed between change to resource rights and when it needs to happen (is it immediate or within a few minutes?)? What high-level role frameworks do you expect to have (IE Security Admin, Security Worker, User, Super User etc.)? What's the rate of change?
Generally I think you want to store resource rights with a user rather than vice versa, as then you have more options around master user control instead of master resource control (IE - someone gets fired it's much easier to just shut down a centralized master user record that's the reference for all other rights)
Is this a "people own stuff but some people are helpers that need to see everything except in sensitive cases then only a few can" type thing?
WRITING FUCKING TAKES JUST AS LONG AS JUST WRITING GOD-DAMN
AND ONE OF THESE PROVIDES USEFUL INFORMATION WHEN YOUR FUCKING INSANE "MANUALLY EDIT /ETC/PASSWD/ AND DON'T USE THE SYSTEM TOOLS" CODE BREAKS!
I feel like a specific event drove you to provide us with this quick protip.
I thought it was part of the GNU compiler suite or whatever?
This code has always been on GNU/C and is not switching off of it in the foreseeable future.
// TODO: Reply
// Rev 2: think about agreeing?
// Rev 3: fix typo how did this even compile?
Welp, deffo no excuses then!
To follow up: syslog() is part of Standard UNIX(tm), not just GNU Libc. And we're sure as hell not moving off of a UNIX-like anytime soon.
To answer:
-New resources are popping in all the time created by users.
-Changes to rights happen immediately
-Most of the roles are not really IT type of roles, rather they are more like organizational and company type roles.
-Rate of change, once a role is defined it usually doesn't need to change.
I could store resource rights with a user, but then it makes it a cumbersome experience when you have for example a "Service Department" role with 10 users and they all need the same level of access to certain resources of a subset of users.
If someone is fired there is a user record in the database that could simply have a disabled flag set that would prevent them from logging in or using any API routes.
It is a "people own stuff but some people are helpers that need to see everything except in sensitive cases then only a few can" type of thing.
I already have a roles system implemented that allows for fine-grain control of what users can and can't do based on activities. Resource access though is still a harder problem to design for because of the variable amount of users over time.