C# question - Page 1
Forum section: electronics / projects

author: DavidDLC
author_rank: Frequent Contributor
timestamp: August 08, 2018, 06:09:49 am
content: I want to make a Fluke287Class, then I want to create an object from this class named Fluke287:Fluke287Class Fluke287 = new Fluke287Class();Then I want to have:Fluke287.Configure.Range(Some value) orFluke287.Measure.Voltage()How can I achieve this ? I cannot do it with nested classes, because I want to create the object from the class and not a static class.David DLC

author: rjp
author_rank: Regular Contributor
timestamp: August 08, 2018, 09:00:28 am
content: you would make the sub object public and then create them inside the toplevel class constructor.Code:class TheSub {}class TheTop {public TheSub Sub { get; protected set; }public TheTop(){Sub = new TheSub();}}

author: Ash
author_rank: Regular Contributor
timestamp: August 08, 2018, 09:50:19 am
content: Quote from: DavidDLC on August 08, 2018, 06:09:49 amHi David,You can certainly warp the C# to achieve this, similar to what rjp suggested.. (though I'd make the Sub classes private and inside the outer class) but really the question is why?This is a very uncommon way to do this. The problem is that I assume you will have some sort of connection that all the sub object then need to share.. And how do you deal with conflicting setup? IE set an invalid range then try to measure something?What's wrong with:Code:enum VoltageRange{Millivolts_100,Volts_1,Volts_10,// etc}enum CurrentRange{Milliamps_100,Amps_1,Amps_10,// etc}class Fluke287{public Fluke287(/*some connection settings here*/) {...}public double MeasureVoltage(VoltageRange range) {...}public double MeasureCurrent(CurrentRange range) {...}}var fluke287 = new Fluke287(/*some connection settings*/);fluke287.MeasureVoltage(VoltageRange.Volts_10);fluke287.MeasureCurrent(CurrentRange.Milliamps_100);Then everything is available at the sample place and time.. The range can be set (if not already correct, assuming you track it in the object) and then the measurement take. The enums restrict the valid range of settings (and are different for voltage and current)..[EDIT: Sorry, I accidentally posted before I finished writing]

author: bd139
author_rank: Super Contributor
timestamp: August 08, 2018, 09:52:10 am
content: I wouldn't heavily namespace like that to be honest unless you're going to program via interfaces for different devices.Here's how I'd do this as a one off:Code:var fluke = new Fluke289();fluke.SetFunction(Fluke289Function.Voltage);fluke.SetRange(Fluke289Range.mV100);var result = fluke.Measure();Nothing at all happens other than mutating private variables until you call Measure();I wouldn't have separate measurement methods for each type unless you are using derived types which isn't worth it as what you're returning is a double usually regardless of the range.Edit: to note you probably can't SetFunction unless you have a bench DMM with total software control of functions. Twirly knob DMM this is pointless. Better to write a thin layer over the SCPI interface if you can just to add type safety to the meter's programming interface.

author: IanB
author_rank: Super Contributor
timestamp: August 08, 2018, 09:52:22 am
content: Quote from: DavidDLC on August 08, 2018, 06:09:49 amJust FYI, this isn't really a natural way to code this. There is no need to call a class "Fluke287Class" because it is already known to be a class. The word "Class" in the name is redundant. So a more canonical way to do it would be like this:Code:var meter = new Fluke287();The reason for calling the reference "meter" is that you might at some point wish to have a base class or interface that represents DMMs in general. Then the Fluke287 class would be a specialization that represents that specific meter. In future you might also have a version for the Brymen 869s, in which case you might then write:Code:var meter = new Brymen869();Everything about "meter" would work just the same whichever kind of meter it happened to be, which would save you re-writing your program for different meters. You would just implement a new meter class for each kind of meter you wish to support.

author: bd139
author_rank: Super Contributor
timestamp: August 08, 2018, 09:55:08 am
content: Honestly it's not worth building a generic interface for this unless you're shipping a product. It's a difficult thing to do. Seriously. I have done itYou then start the following list of questions:1. What if different meters have different communciation protocols2. How do you handle range differences between meters.3. How do you handle dual measurements4. How do you handle meters which can set range and some that can't.5. How do you handle probe alert.6. How do you handle triggered/sync reads versus sampling measurements.7. How do you handle interface lock out and synchronising state of the meter with the software (if someone hits a button)8. Numerous other annoying concerns.

author: IanB
author_rank: Super Contributor
timestamp: August 08, 2018, 11:44:31 am
content: Quote from: bd139 on August 08, 2018, 09:55:08 amYour list of questions is very valid. You would not go to the trouble of creating a generic interface for the first meter. However, once you have implemented a second and a third, you will start to see common or repeated code, at which point you will likely want to factor that out into a shared base class. And from there a generic interface becomes a logical step.

author: DavidDLC
author_rank: Frequent Contributor
timestamp: August 08, 2018, 05:11:05 pm
content: Quote from: IanB on August 08, 2018, 09:52:22 am

author: DavidDLC
author_rank: Frequent Contributor
timestamp: August 08, 2018, 05:27:35 pm
content: Quote from: bd139 on August 08, 2018, 09:52:10 amI know that, I took the wrong model to ask for my original question.

author: DavidDLC
author_rank: Frequent Contributor
timestamp: August 08, 2018, 05:37:16 pm
content: I want to have:Fluke287.Measure.Voltage() <-- This directly indicates me I want to measure voltageFluke287.Measure() <-- This does not indicate me what I want to measureFluke287.Measure("Voltage") <-- I rather like Fluke287.Measure.Voltage()David DLC

author: Wilksey
author_rank: Super Contributor
timestamp: August 08, 2018, 08:57:01 pm
content: Project namespace would be Fluke287, class namespace would be Measure, function would be Voltage()Am I missing something?

author: rjp
author_rank: Regular Contributor
timestamp: August 09, 2018, 01:20:28 am
content: personally i would do.Code:public abstract class DMM{abstract public double MeasureVoltage();}public class Fluke287 : DMM{public override double MeasureVoltage() { return blah; }}that is clear and extendable.

author: Ash
author_rank: Regular Contributor
timestamp: August 09, 2018, 02:09:38 am
content: Quote from: DavidDLC on August 08, 2018, 05:37:16 pmwhat is wrong with:Code:fluke287.MeasureVoltate();fluke287.MeasureCurrent();//etcSame distinction, different method names, and without the nested object headache.Ash.

author: DavidDLC
author_rank: Frequent Contributor
timestamp: August 14, 2018, 02:00:02 am
content: NET Framework has a lot of nesting on itself, these are just some examples of many they have:System.IO.IsolatedStorage.IsolatedStorageFileStreamSystem.IO.DirectorySo why people say havingFluke287.Measure.CurrentFluke287.Measure.VoltageIs not a good way of programming this.I thought it was possible to have a class Measure and with the voltage, current and other methods on itDavid DLC

author: IanB
author_rank: Super Contributor
timestamp: August 14, 2018, 06:23:01 am
content: Quote from: DavidDLC on August 14, 2018, 02:00:02 amThese are namespaces for organizing things. A bit like "Floor 2, aisle 3, 3rd shelf down" in a library.QuoteBecause what you are writing here is something different and doesn't seem to make a lot of sense.QuoteEverything is possible. Not everything is sensible.You still haven't answered what "Measure current" is supposed to do if the meter has a voltage range selected?

author: Tony_G
author_rank: Super Contributor
timestamp: August 14, 2018, 04:09:46 pm
content: You can see how it is implemented in the reference source. For example System.IO.Directory that DavidDLC mentioned is located here:https://referencesource.microsoft.com/#mscorlib/system/io/directory.cs,b3ad5f0ba800bb28And System.IO.IsolatedStorage.IsolatedStorageFileStreamhttps://referencesource.microsoft.com/#mscorlib/system/io/isolatedstorage/isolatedstoragefilestream.cs,3170da5a80264939As IanB said, these are namespace conventions and not nested classes. All of this code should have been run through FxCop as a checkin gate so design & naming should be a reasonable point for copying design.TonyG

author: alexanderbrevig
author_rank: Frequent Contributor
timestamp: August 14, 2018, 05:10:31 pm
content: It kind of looks like the Method Chaining pattern.https://en.m.wikipedia.org/wiki/Method_chainingIf you want to nest classes then you could use dependency injection to f.ex configure the Measure instance according to which DMM you instantiate, maybe implementing different transport layers?Do not new it in the constructor. Either take an instance or have DI fetch one for you.

author: DavidDLC
author_rank: Frequent Contributor
timestamp: August 15, 2018, 05:41:17 am
content: QuoteEverything is possible. Not everything is sensible.You still haven't answered what "Measure current" is supposed to do if the meter has a voltage range selected?Measure.Current will display a message saying the meter is not set for current measurement