I am trying to create an object from an Active Directory base on a simple login. The problem is that some of the login information is valid.
How could I just use a try-catch so that if an exception is thrown, just skip to the next login?
Here is the code:
foreach (var PharosUserItem in ListRef)
{
ADUser User;
try
{
User = new ADUser(PharosUserItem.UserLoginPharos);
}
catch (ByTel.DirectoryServices.Exceptions.UserNotFoundException ex)
{
break;
}
}
The break gets me out of the foreach, which is not what I want. Any ideas?
You are looking for continue
foreach (var PharosUserItem in ListRef)
{
ADUser User;
try
{
User = new ADUser(PharosUserItem.UserLoginPharos);
}
catch (ByTel.DirectoryServices.Exceptions.UserNotFoundException ex)
{
continue;
}
}
Use the continue statement instead:
foreach (var pharosUserItem in ListRef)
{
ADUser user;
try
{
user = new ADUser(pharosUserItem.UserLoginPharos);
}
catch (UserNotFoundException)
{
continue;
}
// Use "user" here
}
(I've made a few changes in terms of variable casing, avoiding using a massively long fully-qualified name for the exception, and providing a variable for the exception which you then ignore.)
Note that if there's any reasonable way that you could get a list of valid users and check it, that would be nicer than using the exception for flow control as you're doing here. It may not be feasible, but it's worth checking :)
You have to use continue;
Use the continue statement to skip to the next iteration.
Rather than throwing an exception, instead you should try and check if the user is valid first. Throwing exceptions is quite expensive and should really only be used in 'exceptional' circumstances and not to control the logical flow of the app, this isn't what they should be used for as you are expecting some users to fail.
why not use nothing instead of continue?
Use the continue statement instead:
foreach (var pharosUserItem in ListRef)
{
ADUser user;
try
{
user = new ADUser(pharosUserItem.UserLoginPharos);
}
catch (UserNotFoundException)
{
}
// Use "user" here
}
or put a
console.writeline("user not found: "+ pharosuseritem.tostring() );
Related
I'm working with the following code, but I'm not sure how is the proper way to do it.
try
{
// Do code for Try1
Console.WriteLine("Try1 Successful");
}
try
{
// If try1 didn't work. Do code for Try2
Console.WriteLine("Try2 Successful");
}
try
{
// If try2 didn't work. Do code for Try3
Console.WriteLine("Try3 Successful");
}
catch (Exception)
{
// If try1, 2 and 3 didn't work. print this:
Console.WriteLine("The program failed");
}
What I want is to try 3 different ways of a task, and if the 3 of them fail, print "The program failed", but if one of them is successful, don't do the other ones and continue with the program
Edit:
The task that I am trying to do, is looking for a NETWORK PATH.
The Task 1 will look if a path can be opened, if so OPEN THE DIRECTORY.
If not: Task 2 will look if a second path can be opened, if so OPEN THE DIRECTORY.
If not: Task 3 will look if a third path works, if so OPEN IT.
If not "no paths can be found on this pc"
You can make it without try catch block.
For the simplicity make that Task1, Task2, Task3, have some kind of return types.
For example if they return boolean type. TRUE if Task succededd or FALSE if Task failed.
Or they can return some custom type with boolean result, and string error message. I would not go with nested try catch blocks.
executeTasks() {
Console.WriteLine("Try 1");
if (Task1()) return;
Console.WriteLine("Try 2");
if (Task2()) return;
Console.WriteLine("Try 3");
if (Task3()) return;
Console.WriteLine("The program failed");
}
Hopefully this snippet can be easily adapted to meet your needs.
namespace StackOverflow69019117TryCatch
{
using System;
using System.IO;
public class SomeClass
{
public void MainMethod()
{
var paths = new string[] {
#"C:\Users\otherUser\Documents", // exists but I don't have access to it
#"C:\temp", // exists but doesn't contain the folderToSearchFor subfolder
#"Z:\doesntexist", // doesn't exist
};
foreach (var path in paths)
{
Console.WriteLine($"Trying with path {path}");
if (this.ProcessDirectory(path, "folderToSearchFor"))
{
// We've succeeded so exit the loop
Console.WriteLine($"Succeeded using path {path}");
return;
}
else
{
// We've failed so continue round the loop and hope we succeed next time
Console.WriteLine($"Failed using path {path}");
}
}
}
private bool ProcessDirectory(string directoryPath, string folderToSearchFor)
{
// First, check whether the directory we want to search actually exists.
if (!Directory.Exists(directoryPath))
{
// Then the directory we're trying to search in doesn't exist.
// Return false, no need to incur the overhead of an exception.
Console.WriteLine($"Directory {directoryPath} doesn't exist");
return false;
}
// This doesn't appear to throw an exception if directoryPath isn't accessible to the current user.
// Instead it just returns whatever the current user has access to (which may be an empty array).
var propFolderCandidates = Directory.GetDirectories(directoryPath, $"{folderToSearchFor}*");
// But did it return anything?
// If not then what we're looking for either doesn't exist or the user doesn't have access to it.
if (propFolderCandidates.Length == 0)
{
// Then there's no folder here matching the search path.
// Return false, no need to incur the overhead of an exception.
Console.WriteLine($"Couldn't find folder matching {folderToSearchFor} in {directoryPath}");
return false;
}
var propFolder = propFolderCandidates[0];
// Consider implementng similar checks in Process.Start.
// e.g. if it's reading a file, check whether the file exists first
if (Process.Start(propFolder))
{
Console.WriteLine($"Process.Start succeeded using {directoryPath}");
return true;
}
else
{
Console.WriteLine($"Process.Start failed using {directoryPath}");
return false;
}
}
}
}
As #BionicCode has pointed out in various comments, it's less expensive to check whether an action might throw an exception before performing that action, than it is to perform the action and then handle the exception if it's thrown by the action.
I had to do a bit of digging to establish what happens when Directory.GetDirectories tries to get the subfolders of a folder that the current user doesn't have access to - I was expecting it to throw an exception, but it seems that it doesn't, it just returns an empty array representing the nothing that the current user has access to in that location, so no exception to handle in that scenario.
Throwing and catching of exceptions definitely has its place in .net software, but you should treat it as something to fall back on if something happens which you can't anticipate at design time - if there's a way at design time of detecting that a particular action isn't going to work, then you should detect it and report to the caller that the action they've requested won't work, rather than performing the action and trying to handle any exception it might throw.
There is some wise advice from Microsoft on the subject of best practice for exceptions.
Use exception handling if the event doesn't occur very often, that is, if the event is truly exceptional and indicates an error (such as an unexpected end-of-file). When you use exception handling, less code is executed in normal conditions.
Check for error conditions in code if the event happens routinely and could be considered part of normal execution. When you check for common error conditions, less code is executed because you avoid exceptions.
Hope this is useful :-)
You're gonna have to nest your try-catch blocks:
try {
Console.WriteLine("Try1 successful");
} catch {
try {
Console.WriteLine("Try2 successful");
} catch {
try {
Console.WriteLine("Try3 successful");
} catch {
Console.WriteLine("The program failed");
}
}
}
I have already found a way, to be honest I don't know if this is the best way, but totally works.
The solution was to nest a few try-catch(exception)
This is what I am doing...
try
{
try
{
//Check if PROP can be found inside initial path A
string[] PROP_FOLDER = Directory.GetDirectories(Full_PathA, $"{PROP}*");
Process.Start(PROP_FOLDER[0]);
//Open PROP in path A and RETURN
status_label.Text = " Found it!";
status_label.ForeColor = Color.LimeGreen;
}
catch (Exception) //If an error occurs on path A
{
try
{
//Check if PROP can be found inside initial path B
string[] PROP_FOLDER = Directory.GetDirectories(Full_PathB, $"{PROP}*");
Process.Start(PROP_FOLDER[0]);
//Open PROP in path B and RETURN
status_label.Text = " Found it!";
status_label.ForeColor = Color.LimeGreen;
}
catch (Exception) //If an error occurs on path B
{
//Check if PROP can be found inside initial path C
string[] PROP_FOLDER = Directory.GetDirectories(Full_PathC, $"{PROP}*");
Process.Start(PROP_FOLDER[0]);
//Open PROP in path C and RETURN
status_label.Text = " Found it!";
status_label.ForeColor = Color.LimeGreen;
}
}
}
catch (Exception) //If PROP cannot be found on any of those paths, the PROP doesn't exist
{
status_label.Text = " Not Found!";
status_label.ForeColor = Color.Red;
}
I have a nested foreach loop, and I would like to know which is the best way to skip a record based on an if condition in c#.
Below is my solution, if there are any improvements or suggestions please do let me know.
foreach (var ospMap in sourceSpecificMaps)
{
foreach (var idMapSensorId in ospMap.SensorIds)
{
try
{
if (string.IsNullOrEmpty(idMapSensorId.SourceId))
{
throw new Exception($"SourceId couldn't be found in the { idMapSensorId.SensorId } sensor. The sensor is being skiped.");
}
_ospIdMapDictionary[GenCacheId(sourceId, idMapSensorId.SensorId)] = ospMap;
}
catch (Exception)
{
// We continue through the loop
continue;
}
}
}
Using exceptions like this is both slow (exceptions are very slow) and terrible practice. Just use the continue if you want to skip.
foreach (var ospMap in sourceSpecificMaps)
{
foreach (var idMapSensorId in ospMap.SensorIds)
{
if (string.IsNullOrEmpty(idMapSensorId.SourceId))
{
continue; // TODO: Log the follwoing ? SourceId couldn't be found in the { idMapSensorId.SensorId } sensor. The sensor is being skiped
}
_ospIdMapDictionary[GenCacheId(sourceId, idMapSensorId.SensorId)] = ospMap;
}
}
You are using exceptions to control logic flow, which is generally a bad idea. Unless you are actually going to do something with that exception, get rid of it and just put the continue inside that if statement.
I think you can remove your try catch if you don't need it for a logical process,
Then you will have code like this :
foreach (var ospMap in sourceSpecificMaps)
{
foreach (var idMapSensorId in ospMap.SensorIds)
{
if (string.IsNullOrEmpty(idMapSensorId.SourceId))
{
continue; // SourceId couldn't be found in the { idMapSensorId.SensorId } sensor. The sensor is being skiped
}
_ospIdMapDictionary[GenCacheId(sourceId, idMapSensorId.SensorId)] = ospMap;
}
}
with linq you could do something like this:
var list = outerList.SelectMany(x => x.TheInnerList).Where(n => !string.IsNullOrEmpty(n.Id));
I think to iterate over those elements based on a initial condition is a cleanest way to do the job
What you want is something like this:
foreach (var ospMap in sourceSpecificMaps)
{
foreach (var idMapSensorId in ospMap.SensorIds)
{
if (string.IsNullOrEmpty(idMapSensorId.SourceId))
{
// SourceId couldn't be found in the sensor. The sensor is being skipped.
continue;
}
_ospIdMapDictionary[GenCacheId(sourceId, idMapSensorId.SensorId)] = ospMap;
}
}
As everyone above has mentioned, unless you are throwing an exception and the only way to properly handle the error condition caused by the exception is to catch is somewhere outside the loop, don't use exceptions for control flow. They are, compared to a simple conditional test, extremely slow and resource intensive. Especially in a loop, if you get a ton of empty sourceIds this approach could seriously affect your apps performance.
And in your example, again as others have said, you are not actually 'handling' the exception. You are just ignoring it and skipping the remaining body of the loop after the 'if' statement. The exact same behavior results from the code above.
With C# can we use continue outside foreach? I mean can we skip exception scenarios and move to next record validation ? As per my scenario, I have to refactor code to a separate method instead of using continue in the foreach loop.
foreach (var name in Students)
{
//forloop should continue even if there is any logic exception and move to next record
CheckIfStudentExist();
}
private void CheckIfStudentExist()
{
try
{
//do some logic to verify if student exist & take to catch if there is some error in logic
}
Catch(Exception)
{
continue;
}
}
You can't write continue statement outside loop block.
If you want exception to be silent, just leave catch block empty.
private void CheckIfStudentExist()
{
try
{
//do some logic to verify if student exist & take to catch if there is some error in logic
}
catch
{
}
}
However, empty catch block is a bad practice. At least write some log statement inside so the exception is not lost forever.
It's better to declare our own business exception class so we can catch specific exception type and leave other type (possibly fatal) of exceptions to halt our code execution.
private void CheckIfStudentExist()
{
try
{
//do some logic to verify if student exist & take to catch if there is some error in logic
}
catch(ValidationException e)
{
// example of the log statement. Change accordingly.
Log.Error(e, "Validation failed when validating student Id {0}", studentId);
}
}
If I have the following code:
List<MyClass> list = GetList();
list.ForEach(i => i.SomeMethod());
and let's say SomeMethod() throws an exception. Does ForEach continue iterating, or does it just stop right there?
If it does terminate, is there any way to get the rest of the items in the collection to run their methods?
Yes, if an exception is thrown, the loop exits. If you don't want that behaviour, you should put exception handling into your delegate. You could easily create a wrapper method for this:
public static Action<T> SuppressExceptions<T>(Action<T> action)
{
return item =>
{
try
{
action(item);
}
catch (Exception e)
{
// Log it, presumably
}
};
}
To be honest, I would try to avoid this if possible. It's unpleasant to catch all exceptions like that. It also doesn't record the items that failed, or the exceptions etc. You really need to think about your requirements in more detail:
Do you need to collect the failed items?
Do you need to collect the exceptions?
Which exceptions do you want to catch?
It would almost certainly be cleaner to create a separate method which used the normal foreach loop instead, handling errors and collecting errors as it went. Personally I generally prefer using foreach over ForEach - you may wish to read Eric Lippert's thoughts on this too.
It will throw an error. You're also well on your way to reimplementing foreach. How about just:
foreach (var item in list)
{
try
{
// dangerous thing with item
}
catch (Exception e)
{
// how do you want to log this?
}
}
This has the benefit of working in most versions of .NET and being obviously side-effectful. Of course, you can put this code directly in the ForEach delegate, but I would only suggest that if it's going to be a method itself (rather than a lambda function).
A reasonable alternative is to create your own ForEachWithCatch extension that captures all the exceptions and sends them back to the caller:
public static IEnumerable<Tuple<T,Exception>> ForEachWithCatch<T>(this IEnumerable<T> items, Action<T> action)
{
var exceptions = new List<Tuple<T,Exception>>();
foreach(var item in items)
{
try
{
action(item);
}
catch(Exception e)
{
exceptions.Add(Tuple.Create(item, e));
}
}
return exceptions;
}
This sends back an enumerable of each item that failed and it's corresponding exception.
If your SomeMethod has implemented try-catch block then foreach will continue
void SomeMethod()
{
try
{
//Some operation on i
}
catch(Exception ex)
{
}
}
But if not then foreach will break.
One what of doing it is this way
list.ForEach(i =>
{
try
{
i.SomeMethod();
}
catch(Exception ex)
{
}
});
But its always good to have zero try-catch blocks in your code. Else you will never find where the culprit is.
class Program
{
static void Main(string[] args)
{
var getfiles = new fileshare.Program();
string realname = "*test*";
string Location = "SVR01";
foreach (var file in getfiles.GetFileList(realname,Location))
{getfiles.copytolocal(file.FullName); }
}
private FileInfo[] GetFileList(string pattern,string Location)
{
try
{
switch (Location)
{
case "SVR01":
{
var di = new DirectoryInfo(#"\\SVR01\Dev");
return di.GetFiles(pattern);
}
case "SVR02":
{
var di = new DirectoryInfo(#"\\SVR02\Dev");
return di.GetFiles(pattern);
}
case "SVR03":
{
var di = new DirectoryInfo(#"\\SVR03\Prod");
return di.GetFiles(pattern);
}
default: throw new ArgumentOutOfRangeException();
}
}
catch(Exception ex)
{ Console.Write(ex.ToString());
return null;
}
}
private void copytolocal(string filename)
{
string nameonly = Path.GetFileName(filename);
File.Copy(filename,Path.Combine(#"c:\",nameonly),true);
}
}
Am handle the default switch statement but not sure am doing right,some one please correct me .
Thanks in Advance
You should throw an exception only in cases where you don't expect something to happen. If a directory other than SRV01/02/03 is not expected, throwing exception could be fine. If you expect it to happen and want to handle it gracefully, don't throw an exception.
But catching the exception you just threw and writing it to the console in the same function doesn't make sense. You kill all the purpose of throwing an exception there. If you want to write an error to the console, you can do that directly in the default statement.
If you want to handle the case when GetFiles throws an exception, handle it specifically. Catching an exception and writing it to console does not make sense. If you catch it, it means that you know what to do with it. If you don't, don't catch it.
Say your network is dead and GetFiles raises IOException. You catch it and return null and your code will raise NullReferenceException. Because of that, you lose the information about why that exception is raised.
What do you want to do if network connection is lost? You want to exit? Then you don't need to do anything, an unhandled exception already does that for you. You need to continue running? Are you sure? If app exits successfully will it mean "it has completed everything it's supposed to do" or "there could have been problems but you don't care"? If you're sure it's ok to "ignore" the error, then catch the exception, inform and continue, it's fine. Just make sure of your intent. Exceptions aren't bad or evil. They are there because they are helpful.
I see that you simply need to check if a location is in a list of allowed locations. I don't think a switch is a good candidate for something like this. It looks more like configuration, maybe something along the following lines would allow you to read such values from a configuration file for example. Also the logic in each switch statement is the same, so if we can minimise this repetition, it's a bonus
private List<string> _allowedLocations
public YourClassConstructor()
{
_allowedLocations = new List()
{#"\\SVR01\Dev", #"\\SVR02\Dev", #"\\SVR02\Dev"}
}
private FileInfo[] GetFileList(string pattern,string location)
{
if (location == null)
throw new ArgumentNullException("location");
if (!_allowedLocations.Contains(location))
throw new ArgumentOutOfRangeException("location");
var di = new DirectoryInfo(location);
return di.GetFiles(pattern);
}
The default in a switch statement is basically a catch all (or what youre doing in your catch statement). If something lands in your switch statement and hits the default, it may as well gone to your catch. My suggestion, return a null and write to the console whatever your exception is. If your exception works, keep it as is. Like #SLaks said, you can do whatever you want in your default clause, because it is the switches form of a catch statement.
If it's only for an internal environment where you have full control of the network paths, then you have the option to make an enum for location, which would give you the advantage of each possibility showing up in Intellisense. I additionally agree with what Kevin pointed out, in that you are throwing the exception only to catch it yourself within the same method (an antipattern). The enum is my only suggestion, otherwise your understanding and implementation of default is correct (i.e., to catch all unexpected/invalid cases).