I have my code and I would like to optimize it. For me it looks like it's already optimized. Can anyone suggest how I could make it a bit more optimized?
if (target == "power")
{
return new JsonResult { Data = new { RC = new Data.AdminPower(datastoreValue).Refresh() } };
}
if (target == "notes")
{
return new JsonResult { Data = new { RC = new Data.AdminNotes(datastoreValue).Refresh() } };
}
if (target == "book")
{
return new JsonResult { Data = new { RC = new Data.AdminBook(datastoreValue).Refresh() } };
}
return null;
switch statements are great for these situations:
switch(target)
{
case "power":
return new JsonResult { Data = new { RC = new Data.AdminPower(datastoreValue).Refresh() } };
case "notes":
return new JsonResult { Data = new { RC = new Data.AdminNotes(datastoreValue).Refresh() } };
case "book":
return new JsonResult { Data = new { RC = new Data.AdminBook(datastoreValue).Refresh() } };
default:
return null;
}
Dont really need the breaks tho, since it will be returning each time, but its good practice..
If you know that your method will be called more often with "book" values, then you should put that first. Basically sort by order of frequency.
As someone else mentioned, you should put them in order of most likely to occur to minimize your total number of incorrect comparisons.
Maybe it's possible to change "power" "notes" and "book" to an enum or int representation, and that may be slightly faster than the string comparisons.
There's not a whole lot you can do that will result in any significant optimizations, though.
I don't know what's your idea about optimized,
as a matter of speed, just put some 'else' before second and third 'if's
but if you mean less code lines, then may be something like this could help you:
return
((target == "power") ? new JsonResult { Data = new { RC = new Data.AdminPower(datastoreValue).Refresh() } } :
((target == "notes") ? new JsonResult { Data = new { RC = new Data.AdminNotes(datastoreValue).Refresh() } } :
((target == "book") ? new JsonResult { Data = new { RC = new Data.AdminBook(datastoreValue).Refresh() } } : null))))
The only thing I would do is change the ifs to an if-elseif chain. There isn't really anything else you can do to improve performance.
Related
I'm working with TwincatAds.Reactive 6.0.190 in .NET 6 WPF Desktop application.
I'm also using MVVM pattern.
My goal is to create a Class that is going to observe for a PLC Variable changes, collect those variables to a dictionary, and later on use those values in the ViewModel.
Here's the method where I'm attaching the notification and action where I'm handling the notification.
public void AttachNotification(IEnumerable<(string key, Type type)> Symbols)
{
_observerValueNotification = Observer.Create<ValueNotification>(val =>
{
// Does handle really start from 2?
var handle = val.Handle;
if (val.UserData is object[] objects)
{
string tag = objects[handle - 2].ToString();
if (!_values.Any(x => x.Key == tag))
_values.Add(new SymbolModel { Key = tag, Value = val.Value });
else
{
var symbol = _values.First(x => x.Key == tag);
symbol.Value = val.Value;
}
}
ValuesChanged?.Invoke(_values);
});
if (_plcWrapper.AdsClient != null)
{
// Get Symbols from SymbolLoader
List<AnySymbolSpecifier> list = new();
List<string> userData = new();
foreach (var (key, type) in Symbols)
{
list.Add(new AnySymbolSpecifier(key, new AnyTypeSpecifier(type)));
userData.Add(key);
}
_subscription2 = _plcWrapper.AdsClient.WhenNotificationEx(list, NotificationSettings.ImmediatelyOnChange, userData.ToArray())
.Subscribe(_observerValueNotification);
}
}
I'm using ValueNotification simply because, I'd like to use this pattern also for complex PLC Variables like Structs.
As You can see, in the WhenNotificationEx method I'm using UserData[] to provide some sort of identification of what Variable has changed when handling the change.
My idea was to use Handle property from ValueNotification as an indexer in UserData[] to identify what variable I'm dealing with, but for some reason Handle starts from 2.
My question is, is it expected behaviour, does the Handle value really always start from 2?
I've decided that relying on the Handle being index in the UserData array is quite unpredictable as Handle is being created by the Twincat Ads server.
Solved the issue by creating own extension method to the WhenNotificationEx. Turned out IDisposableHandleBag has exactly what I was looking for, which is SourceResultHandles property, where AnySymbolSpecifier and ResultHandle are both stored!
Here's created extension method
public static Dictionary<string, uint> Handles { get; private set; } = new();
public static IObservable<ValueNotification> WhenNotificationWithHandle(this IAdsConnection connection, IList<AnySymbolSpecifier> symbols, NotificationSettings settings)
{
IAdsConnection connection2 = connection;
IList<AnySymbolSpecifier> symbols2 = symbols;
NotificationSettings settings2 = settings;
if (connection2 == null)
{
throw new ArgumentNullException("connection");
}
if (symbols2 == null)
{
throw new ArgumentNullException("symbols");
}
if (symbols2.Count == 0)
{
throw new ArgumentOutOfRangeException("symbols", "Symbol list is empty!");
}
IDisposableHandleBag<AnySymbolSpecifier> bag = null;
EventLoopScheduler scheduler = new EventLoopScheduler();
IObservable<int> whenSymbolChangeObserver = connection2.WhenSymbolVersionChanges(scheduler);
IDisposable whenSymbolChanges = null;
Action<EventHandler<AdsNotificationExEventArgs>> addHandler = delegate (EventHandler<AdsNotificationExEventArgs> h)
{
connection2.AdsNotificationEx += h;
bag = ((IAdsHandleCacheProvider)connection2).CreateNotificationExHandleBag(symbols2, relaxSubErrors: false, settings2, null);
bag.CreateHandles();
// Collect Handles
Handles.Clear();
foreach (var item in bag.SourceResultHandles)
Handles.Add(item.source.InstancePath, item.result.Handle);
whenSymbolChanges = whenSymbolChangeObserver.Subscribe((Action<int>)delegate
{
bag.CreateHandles();
Handles.Clear();
foreach (var item in bag.SourceResultHandles)
Handles.Add(item.source.InstancePath, item.result.Handle);
}, (Action<Exception>)delegate
{
TcTraceSource traceAds = AdsModule.TraceAds;
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(101, 1);
defaultInterpolatedStringHandler.AppendLiteral("The AdsServer '");
defaultInterpolatedStringHandler.AppendFormatted(connection2.Address);
defaultInterpolatedStringHandler.AppendLiteral("' doesn't support SymbolVersionChanged Notifications! Handle recreation is not active!");
traceAds.TraceInformation(defaultInterpolatedStringHandler.ToStringAndClear());
});
};
Action<EventHandler<AdsNotificationExEventArgs>> removeHandler = delegate (EventHandler<AdsNotificationExEventArgs> h)
{
if (whenSymbolChanges != null)
{
whenSymbolChanges.Dispose();
}
scheduler.Dispose();
if (bag != null)
{
bag.Dispose();
bag = null;
Handles.Clear();
}
connection2.AdsNotificationEx -= h;
};
return from ev in Observable.FromEventPattern<EventHandler<AdsNotificationExEventArgs>, AdsNotificationExEventArgs>(addHandler, removeHandler)
where bag.Contains(ev.EventArgs.Handle)
select new ValueNotification(ev.EventArgs, ev.EventArgs.Value);
}
I hope someone can help with this. For a few years now, I've been iterating through my searchresult using a LOT of If statements to populate all of the properties in my class. There are over 300 properties that I need to populate.. but that is an awful lot of if statements. As an example, this is what I mean:
var myCon = StarfishLDAPCon.CreateDirectoryEntry(objectContainer, whichCM);
var ds = new DirectorySearcher(myCon);
ds.Filter = "(deftyAgentID=07629)";
var result = ds.FindOne();
AgentID returnValue = new AgentID();
if (result.Properties.Contains("deftyAgentID"))
{
returnValue.DeftyAgentID = result.Properties["deftyAgentID"][0].ToString();
}
if (result.Properties.Contains("deftySecuritycode"))
{
returnValue.DeftyAgentID = result.Properties["deftySecuritycode"][0].ToString();
}
if (result.Properties.Contains("deftyAgentACWAgentConsdrdIdle"))
{
returnValue.DeftyAgentACWAgentConsdrdIdle = result.Properties["deftyAgentACWAgentConsdrdIdle"][0].ToString();
}
I have over 300 of those if statements. I'm hoping there's some cool way to do this without all those if statements? Anyone have any ideas?
Thanks for any help!
Dave M.
Well pretty simple - just write a small extension method like this:
public static class SearchResultExtension
{
public string GetPropertyValue(this SearchResult result, string propName)
{
if (result == null || result.Properties == null)
{
return null;
}
if (result.Properties.Contains(propName))
{
return result.Properties[propName][0].ToString();
}
return null;
}
}
Now you can handle the 80% "normal" cases like this:
SearchResult result = ds.FindOne();
AgentID returnValue = new AgentID();
returnValue.DeftyAgentID = result.GetPropertyValue("deftyAgentID");
returnValue.DeftySecurityCode = result.GetPropertyValue("deftySecuritycode");
returnValue.DeftyAgentACWAgentConsdrdIdle = result.GetPropertyValue("deftyAgentACWAgentConsdrdIdle");
and so forth. Any cases that should not return the first element of the Properties collection as a string need to be handled separately, obviously
I created a method where i take a random row from ma database and put it into new List, if the method will be used again, it will check if the random row was selected before and chose another one, like drawing without repetition.The program compile, but dont work. Can anyone tell me what i am doing wrong?
TABUEntities baza = new TABUEntities();
IList AlreadyChosen = new List<IList>();
public List<HASLA> RandomWords()
{
List<HASLA> dane = baza.HASLA.OrderBy(x => Guid.NewGuid()).Take(1).ToList();
if (AlreadyChosen.Contains(dane))
{
RandomWords();
}
AlreadyChosen.Add(dane);
return dane;
}
if (AlreadyChosen.Any(a=>a.SomeUniqueProperty == dane.SomeUniqueProperty))
You have to search by some unique property like Id to make sure you can find the object. Also if you want to use Contains then you will have to implement and override the IComparable interface and methods, or pass a custom comparer.
Try this
TABUEntities baza = new TABUEntities();
List<HASLA> AlreadyChosen = new List<HASLA>();
public List<HASLA> RandomWords()
{
List<HASLA> rw = new List<HASLA>();
rw.addRange(AlreadyChosen);
HASLA selectedObj = baza.HASLA.Where(y => !AlreadyChosen.Contains(y)).OrderBy(x => Guid.NewGuid()).Take(1).FirstOrDefault();
if ((selectedObj == null)) {
return rw;
} else {
if (AlreadyChosen.Contains(selectedObj)) {
return RandomWords();
} else {
AlreadyChosen.add(selectedObj);
return RandomWords();
}
}
}
I have a class called LinearTransformation whose values I want to set during execution so that they are used next time, and then can be overwritten, etc.
Currently, I am verifying if there is a previous value and, if not, I set that value to a default one.
The problem is: my code has become repetitive, ugly, and most of it will only be useful the first time a new installation is run on a client machine.
Is there a more elegant way to achieve this?
// This method is run when the app starts
private void LoadCalibrações()
{
if (Properties.Settings.Default.CalibXEsq == null)
{
Properties.Settings.Default.CalibXEsq = new TransformaçãoLinear();
}
if (Properties.Settings.Default.CalibYEsq == null)
{
Properties.Settings.Default.CalibYEsq = new TransformaçãoLinear();
}
if (Properties.Settings.Default.CalibXDir == null)
{
Properties.Settings.Default.CalibXDir = new TransformaçãoLinear();
}
if (Properties.Settings.Default.CalibYDir == null)
{
Properties.Settings.Default.CalibYDir = new TransformaçãoLinear();
}
Properties.Settings.Default.Save();
_calibrações = new[]
{
Properties.Settings.Default.CalibXEsq,
Properties.Settings.Default.CalibYEsq,
Properties.Settings.Default.CalibXDir,
Properties.Settings.Default.CalibYDir
};
}
If you just need to fill the array...
var settings = Properties.Settings.Default;
_calibrações = new[]
{
settings.CalibXEsq ?? new TransformaçãoLinear(),
settings.CalibYEsq ?? new TransformaçãoLinear(),
settings.CalibXDir ?? new TransformaçãoLinear(),
settings.CalibYDir ?? new TransformaçãoLinear(),
};
otherwise...
var settings = Properties.Settings.Default;
_calibrações = new[]
{
settings.CalibXEsq ?? (settings.CalibXEsq = new TransformaçãoLinear()),
settings.CalibYEsq ?? (settings.CalibYEsq = new TransformaçãoLinear()),
settings.CalibXDir ?? (settings.CalibXDir = new TransformaçãoLinear()),
settings.CalibYDir ?? (settings.CalibYDir = new TransformaçãoLinear()),
};
I'm using Ncalc in my new project and it already has almost everything I need .
I said almost everything, because now I need to expand some functions and also add new ones such as : nth root,random, etc
Do you know if anyone has already implemented those functions? Or could you give me any tips or guides to extend the function list of Ncalc???
Thanks in advance.
If I understand correctly:
As much as I was using it is by creating a static function
private static void NCalcExtensionFunctions(string name, FunctionArgs functionArgs)
{
if (name == "yourfunctionname")
{
var param1 = functionArgs.Parameters[0].Evaluate();
var param2 = functionArgs.Parameters[1].Evaluate();
//... as many params as you require
functionArgs.Result = (int)param1 * (int)param2; //do your own function logic here
}
if (name == "random")
{
if(functionArgs.Parameters.Count() == 0)
{
functionArgs.Result = new Random().Next();
}
else if(functionArgs.Parameters.Count() == 1)
{
functionArgs.Result = new Random().Next((int)functionArgs.Parameters[0].Evaluate());
}
else
{
functionArgs.Result = new Random().Next((int)functionArgs.Parameters[0].Evaluate(), (int)functionArgs.Parameters[1].Evaluate());
}
}
}
And then you use it as follows
var expr = new Expression("yourfunctionname(3, 2)");
expr.EvaluateFunction += NCalcExtensionFunctions;
var result = expr.Evaluate();
var randExpr = new Expression("random(100)");
randExpr.EvaluateFunction += NCalcExtensionFunctions;
var resultRand = randExpr.Evaluate();
I hope I didn't mistype any of the code. A list of NCalc built-in functions can be found here: http://ncalc.codeplex.com/wikipage?title=functions&referringTitle=Home