|
Your class looks pretty good, here are some suggestions to tighten it up:
string[] _clArray;
Don't have members with typenames, this should be _cl (or _cla if the a means something other than array). For one thing it is redundant, secondly it is against naming conventions, thirdly names should be meaningful (using array might make sense in an type classing a solar panel array for example). The Microsoft guidance is not to prefix fields (with "_" for example), but I (and most of the people I know do this, as it is internal other devs won't see it (unless reading your code directly).
You should consider:
public string[] Cla
{
get { return this._clArray; }
private set { this._clArray = value; }
}
private prevents the array instance being changed from outide the class. It does lead to problems filling the array, you can do this with the class's constructor or with a specific array-setting method. Personally I'd go for the generic List<string> mentioned earlier by membernnnnnnn. With this you just create the instance inside the object and then can call the it's add method from the get accesssor. Under various circumstances you might want to make the list totally immutable from outside the class, to do this you should get rid of the public accessor you have and look at collection as readonly[^], you can then add Add and Remove methods etc that perform some validation for example.
Note also Cla your class breaks the normal .net naming conventions, you should try to keep to these: the Microsoft classes are written this way and you will confuse other devs using your code by not doing this.
|
|
|
|
|
"It does lead to problems filling the array"
No it doesn't, arr[i] only uses the get indexer. As you point out later, this is sometimes not what you want and you have to provide a wrapper.
Generally an excellent post though.
|
|
|
|
|
You are quite right, I wasn't at all clear. It would have been better put "You then have the problem of instantiating the array to the correct size for the items you are going to fill it with" which means you need to know how many items you are going to have at the ctor call, or provide a method to instantiate an array of the correct size when you do know.
|
|
|
|
|
Hi experts,
there is an application that can save some data on user request. In the application, data is held in objects that composit larger objects. Their corresponding classes inherit from one another and from abstract base classes. In order to save this all to disk it is thrown at a SoapFormatter.
SoapFormatter can again read the saved file and create the objects as they were before.
In the future, requests will change. So the classes will have to change.
Should there be any new properties to a class, I know I can add it using OptionalFieldAttribute to load. Should properties become obsolete, I can just leave them where they are, don't use them, let the storage get a little bigger than needed and have no problem with it.
How can I handle larger changes?
Is there a way to load the "old" assembly into memory, let it load the old storage file and retrieve the object structure from it programatically?
This way, "new" classes could be able to construct from "old" ones.
Ciao,
luker
|
|
|
|
|
lukeer wrote: Is there a way to load the "old" assembly into memory
Yes. Use an app domain.
But what happens in 2 years when you now have 5 versions?
If you must serialize then it is better to have a migration tool that runs independently from the app. Run it when you install the new version.
You probably better have a way to determine what version the data is in as well.
|
|
|
|
|
jschell wrote: Yes. Use an app domain.
Thanks, I'm going to research this.
jschell wrote: But what happens in 2 years when you now have 5 versions?
Well, I thought if loading the file version-5-style fails, I would have the software use the version 4 assembly, which in turn could revert to yet another earlier version.
jschell wrote: have a migration tool that runs independently
Wouldn't a separate migration tool internally use a similar approach?
jschell wrote: determine what version the data is
I already have every class serialize a version number with it.
The problem here is that if Formatter.Deserialize() fails, the serialized version number is as inaccessible as all the other saved data.
Ciao,
luker
|
|
|
|
|
lukeer wrote: The problem here is that if Formatter.Deserialize() fails, the
serialized version number is as inaccessible as all the other saved data.
Thus you need a different method.
Like a class that has nothing but a version number in it.
|
|
|
|
|
I've got a long running application what reads some data and store it in Dictioinary field.
I persist that class containing dictionary using serialization.
During the application run there is small memory consumtion going on about 1 Mb a minute.
However serialized object grows about 100 bytes a minute or less.
What is the best and fastest way to discover the reason of the leak?
Is it possible to determine exact size of that class with Dictionary collection in memory during the program run?
Чесноков
|
|
|
|
|
You'd use a .NET memory profiler like these[^].
If you're looking in TaskManager to tell you what you're app is using, don't. TM is telling you how much memory is RESERVED by the .NET CLR instance running your app, not the app itself.
|
|
|
|
|
thank you for the link... are there some tools in visual studio or windows to trace the reason of the leak?
Чесноков
|
|
|
|
|
Visual Studio 2010 Premium and Ultimate editions are the only ones with a memory profile built in.
All other editions of 2010 and all editions of Visual Studio 2008 and below do not have a memory profiler at all.
Windows doesn't have any debugging tools to do this either.
But, you are going to have to learn to use the tools effectively. It's not just as simple as starting a profile session, run your app, and Viola!, there's your problem. You have to understand how .NET memory allocation works and how the object involved in your problem behave with respect to memory allocation.
|
|
|
|
|
I have bought an IP cam (Foscam FI8918W) as a baby monitor.
It's great, but one thing that is really lacking is a VU meter.
The cam has an ASF stream accessible through a simple call to http://cam/videostream.asf, which I can easily play in an app with the vlc activeX control.. but in order to build a VU meter I need to be able to analyse the audio stream and this is a little beyond my current programming ability.
I'm going to be a new dad in a couple of weeks and I'd really appreciate any help getting started on this!
|
|
|
|
|
I don't know, but FFT of waveIn audio signals[^] this might help.
I think passing the audio through a fast fourier transform is a good plan. You can then have the monitor report on "baby frequencies" and any loud noise. This is what my [commercial] baby monitor seems to do: The audio is muted until a quiet noise is made in the human voice range, other higher/lower quiet noises are ignored. The thing also unmutes when there is any loud noise. Hopefully others will have better advice as I don't have a lot of experience in this field.
Good luck on the becoming a dad part, I've a [nearly] five month old son. It's the best feeling in the world when they arrive, and it gets better over time. Be prepared for the first week though, it is deeply odd, but in good way! I was exhausted for the first few days as he was delivered by c-section and I had a lot of to-ing and fro-ing to the hospital while my wife convalesced. After the dust has settled from the actual birth, there is an weird mixture of shock (if that is the right word) combined with euphoria . The first night home is odd, newborns make strange noises through the night, and you are on tenterhooks the whole time, I barely slept. A couple of times when he woke me up, I thought an animal got into the room! That said, it was a really, really wonderful time.
|
|
|
|
|
Hi Keith,
In my humble opinion, in an "ideal" CodeProject, there'd be a special place for responses like this which speak so eloquently of the human condition !
best, Bill
"In the River of Delights, Panic has not failed me." Jorge Luis Borges
|
|
|
|
|
You could check this out:
VolumeMeter (Managed DirectX)[^]
Continuous effort - not strength or intelligence - is the key to unlocking our potential.(Winston Churchill)
|
|
|
|
|
Hi,
I have many constants, each recurring as per country and declared in class as below:
class CountryRequests
{
public const string JAP_ABC="JAP_012686";
public const string JAP_PQR="JAP_012457";
public const string JAP_POP="JAP_0178WE";
public const string US_ABC="US_015788";
public const string US_PQR="US_077895";
public const string US_POP="US_8726JI";
public const string EGN_ABC="GB_678756";
public const string ENG_PQR="GB_567766";
public const string ENG_POP="GB_8962KL";
}
and I have multiple functions each accessing string for every country, evaluated as
if(country == 'JAP')
{
}
else if(country == 'US')
{
}
else if(country == 'UK')
{
}
occuring multile times.
What is best coding here. I cannot change from CountryRequests class to collection as it is used by multiple projects.
Please advice.
Thank you.
***** Programme comme si dept soutien technique. est plein de tueurs en série et ils savent adresse de votre domicile. *****
|
|
|
|
|
But in your project you can set a bunch of dictionaries on top of the common CountryRequests class. Using reflection, you should be able to extract all those const string from the class, filter them by their names and set up a dictionary per country.
Then, on changing the country variable you could switch the currently used dictionary, too. That way you wouldn't have to branch in every function.
Ciao,
luker
|
|
|
|
|
Not really sure what you want to know here. If you're saying that you can't change the CountryRequests class, then your options are severely limited.
I imagine you're trying to avoid lots of switch or if statements. As stated, you could try to use a mechanism such as reflection, but I'm not sure that will work with constants as I think they only really exist until the compiler does its stuff. They make it into metadata as well, not sure. (You can get into trouble with constants if you expect them to be late bound - they're not).
Personally, I don't think you should ever build logic which relies on source objects having particular names (concatinating two strings to create a type name you create using Activator.CreateInstance for example). People can change names and things will compile but break at runtime.
Suggestion would be to create one single switch statement which takes a string such as JAP_ABC and returns the constant value of JAP_ABC. You can't avoid doing this sort of thing somewhere, so do it in one place only. Hand coding it will give you compiler checks and detect any changes to the constants on recompiling too.
Regards,
Rob Philpott.
|
|
|
|
|
I agree. Since you can't change the source class, you really don't have any options here.
It's ridiculous to have a Class with nothing but a ton of "magic number" constants in it like this.
This should have been implemented from the start as a Key/Value pair collection, like a Dictionary(). What's odd is that someone should have looked at even this small code snippet and noticed the pattern is just begging to be implemented as a Dictionary.
|
|
|
|
|
I suspect that what you really want is a family of classes, one for each country. (If not a database.)
Even if you can't change the class, you may be able to copy its contents to some other (more suitable) structure via Reflection. This assumes your app runs for a decent length of time rather than only a few seconds at a time.
Another possibility would be to write a little console app that will perform that task at compile time (pre-build event) and yield a file containing the appropriate classes. Your main app would then use the generated classes. This could also be done to yield a single class that only contains a Dictionary of the keys and values.
I'd need to know more about what the app is doing.
|
|
|
|
|
JP_Rocks wrote: I have many constants, each recurring as per country and declared in class as below:
class CountryRequests
{
public const string JAP_ABC="JAP_012686";
public const string JAP_PQR="JAP_012457";
I'd go for an enum, like this;
enum CountryRequests
{
JAP_012686,
JAP_012457
}
That way they're grouped, like constants in a class, and you can still use the string-version by calling JAP_012686.ToString() - that would give you the same result as the content of the constant.
JP_Rocks wrote: What is best coding here
That depends on your type of application. Long lookup-lists are happy in a local embedded database, other times you might want to centralize the information (so that updating it is easy), and move to a central database, or a resource-assembly.
JP_Rocks wrote: I cannot change from CountryRequests class to collection as it is used by multiple projects.
That the class is used often is not an excuse. You can easily write a new class that can be used as a substitute; dive into the "L" part of the SOLID-principle
Bastard Programmer from Hell
|
|
|
|
|
Just refractor the if statement into the CountryRequests class to return the code. I'm guessing there would need to be an extra parameter to handle the ABC, PQR suffix.
public void GetCountryRequestCode(string countryCode)
{
switch (countryCode)
{
Case "JAP":
return JAP_ABC;
....
}
}
"You get that on the big jobs."
|
|
|
|
|
JP_Rocks wrote: I cannot change from CountryRequests class to collection as it is used by multiple projects. One question: is the CountryRequests class in a library that is now being compiled, and which the other projects are now using by embedding a reference to the compiled class ? In other words, are all the projects using CountryRequests under your source-control scope ?
I ask this because of the fact that the compiler in-lines const types where they are referenced, and unless both the CountryRequests class, and all other projects using it are re-compiled together, a client class may persist an out of date value[^].
The idea of using Reflection to pre-compile ... say by using 'Emit ... a "hard-coded" look-up to replace a big Switch statement might be worthwhile if these constant values were being accessed with great frequency, but I doubt that's the case here.
Another idea, based on the constraint that you can't touch 'CountryRequests," would be to create a kind of "singleton" class that effectively "extends" it through inheritance.
disclaimer: experimental: this code tested quickly in VS 2010 Pro, .NET 4.0 Client FrameWork; I have no idea what the implications of using this type of inherited class with call to a private (internal) constructor done by a public static method in a variation on the "singleton" technique, and using a mix of static and public classes might mean in a real-world use case of multi-threaded environment, remoting, multiple consumers of the class, etc.:
public class CountryRequestsServer : CountryRequests
{
internal static CountryRequestsServer instanceCRServer;
internal static Dictionary<string, string> countryLookUp;
internal CountryRequestsServer()
{
countryLookUp = new Dictionary<string, string>()
{
{"JAP", JAP_ABC},
{ "USA", US_POP},
{ "UK", ENG_POP}
};
}
public static string getCountry(string request)
{
if(instanceCRServer == null)
{
instanceCRServer = new CountryRequestsServer();
}
return countryLookUp.ContainsKey(request)
?
countryLookUp[request]
:
"No Match: Input = " + request;
}
} Tested like this:
string myCountryRequest = CountryRequestsServer.getCountry("JAP");
good luck, Bill
"In the River of Delights, Panic has not failed me." Jorge Luis Borges
|
|
|
|
|
BillWoodruff wrote: using Reflection ... with great frequency
In which case I recommend caching the results of the Reflection. Perhaps you meant that, but didn't make it clear.
I don't see that a Singleton gives you any benefit over a static class in this example.
|
|
|
|
|
What you want to do is change this into a family of 'pseudoconstant' instances, or a database table:
public class CountryInfo {
public readonly string ABC, POP, PQR, ...;
private CountryInfo(string abc, string pop, string pqr ...){
ABC = abc; POP = pop; PQR = pqr;
}
public static readonly CountryInfo
JAP = new CountryInfo(CountryRequests.JAP_ABC, CountryRequests.JAP_POP, CountryRequests.JAP_PQR, ...),
UK = new CountryInfo(CountryRequests. UK_ABC, CountryRequests. UK_POP, CountryRequests. UK_PQR, ...),
US = new CountryInfo(CountryRequests. US_ABC, CountryRequests. US_POP, CountryRequests. US_PQR, ...),
}
You still have to define all the constants, but now you don't need to put a switch everywhere. Just pass a CountryInfo (e.g. CountryInfo.JAP) and access the strings through the instance:
void CountryDependentFunction(CountryInfo countryInfo){
someFunction(countryInfo.POP);
}
Even if you don't have enough control to replace or modify CountryRequests, you should be able to put this on top of it. If CountryRequests changes frequently you can write a script to update the lower part of CountryInfo, or you could put some static initialiser reflection in there to load entries at runtime (but then you would have to use a dictionary and indexing and it wouldn't be as nice as using properties, as well as being needlessly complex for most situations).
|
|
|
|
|