Hej! Om du inte vill hantera felet i dll:en, varför gör du det då? Ta bort try/catch så kommer exceptionen till det användande programmet. Jo, jag testade det men blev förbryllad för att felet visade sig i MySQLHandler.dll (som är där metoderna finns enligt ovan). Jo, men är inte det beteendet logiskt? jag tycker inte alls det är logiskt faktiskt. <b>Eftersom jag har faktistk hanterat felet i MySQLHandler.dll; där catch:ar jag och sedan kastar jag felet.</b> Jo, men hela poängen (som jag ser det) med att kasta fel är just att man kastar det till "någon annan" så de ska hantera felet. Det är ju samma sak som att t.ex.: Jo, men hur skall runtimen kunna avgöra att det var programmet som anropade Convert.ToInt32 som skickade med felaktiga värden? null kanske är ett vettigt värde, men pga andra orsaker (kunde t.ex. inte hitta någon fil där format där gilitga värden definieras eller annat yttre beroende) så kanske det blir ett exception. Hu skall runtime:n då kunna avgöra vem som orsakade exceptionet? Alltså, jag menar att programmet kan avgöra det eftersom den vet mycket väl vem det var som anropade metoden. C# Throw exceptions från metoder (DLLer)
Har gjort en MySQL-dll-grej som jag använder i ett projekt. I min MySQLHandler.dll finns det en metod som heter get:
<code>
public Object get(int rowNbr, string column)
</code>
och ett antal andra metoder, typ getInt:
<code>
public int getInt(int rowNbr, string column)
</code>
Anledningen till att jag har getInt, getLong etc är för att jag vill att DLLen ska cast:a till "rätt" (enligt metoden) så man slipper köra convert hit och dit i det program som använder sig av DLL:en.
MEN, då kommer förstås problemet när dessa cast:s inte fugnerar (fel typ, värdet är null eller så). Jag vet ju hur try-catch fungerar, men jag vill eg inte att min MySQLHandler.dll ska hantera de felen. En exception ska komma till huvudprogrammet som använder DLL:en, inte i DLL:en.
Kladdigt? =)
ett par rader ur mitt huvudprogram som använder sig av DLL:en:
<code>
MySQL_Result result = mySqlHandler.executeQuery("SELECT * FROM investigations WHERE id=" + someVar);
// Calculate how many simulations there are to run (different values on the varying variable)
string _variableField = Convert.ToString(result.get(0, "_variableField"));
// ... bla bla... lite annat ...
int percentTransmitters = 100;
percentTransmitters = result.getInt(0, "setting_percentTransmitters");
}
</code>
Om fältet "setting_percentTransmitters" är null i databasen (värdena i MySQL_Result är från min databaas då såklart) så kommer metoden getInt att bli arg då den försöker Convert.ToInt32(...) på fältet. Är den null blir det InvalidCastException. Se koden nedan.
Det finns 2 sätt som jag kan tänka mig:
1) Jag vill att min getInt-metod kan kasta ett fel som sedan mitt "main program" (koden ovan) kan catcha
eller
2) att man kan returnera något vettigt från getInt-metoden. -1 är kasst egentligen för det betyder inte så mkt. Svårt att avgöra om det är ett OK svar eller inte (om man inte kastar in if-satser överallt).
Hoppas jag inte är för flummig. Tacksam för lite input!
MVH
Ted
<code>
public int getInt(int rowNbr, string column)
{
int columnIndex;
try
{
MySQL_Row row = rows[rowNbr];
if (columns.ContainsKey(column))
{
columnIndex = (int)columns[column];
Object o = row.values[columnIndex];
return Convert.ToInt32(o);
}
else
{
Console.Error.WriteLine("There was no column with name '" + column + "'.");
return -1;
}
}
catch (ArgumentOutOfRangeException e)
{
Console.WriteLine("MySQL_Result> getInt(): ArgumentOutOfRangeException occured. The argument " + e.ActualValue + " was out of range.");
return -1;
}
catch (InvalidCastException e)
{
Console.WriteLine("MySQL_Result> getInt(): The requested row and column could not be cast to Int32! " + e.Message);
return -1;
}
}
</code>Sv: C# Throw exceptions från metoder (DLLer)
Om du vill göra egna felmeddelanden är det bara att kasta en egen exception.
throw new Exception("Något blev fel!");
Om du inte hanterar det felet i dll:en så ska det gå vidare.
Ex 1:
<code>
catch (InvalidCastException e)
{
throw new Exception("MySQL_Result> getInt(): The requested row and column could not be cast to Int32! " + e.Message, e);
</code>
Ex 2:
<code>
Object o = row.values[columnIndex];
if (o != null)
return Convert.ToInt32(o);
else
throw new Exception("MySQL_Result> getInt(): The requested row and column could not be cast to Int32!");
</code>Sv:C# Throw exceptions från metoder (DLLer)
Men eftersom jag inte catchade dessa exceptions i mitt "mainProgram" så visade sig felen i DLL:en, vilket jag tycker är galet missvisande.
Om jag nu catchar felet i "mainProgram" fungerar det, men gör jag det inte kommer felet i MySQLHandler.dll, vilket jag inte tycker verkar logiskt. Oavsett vad ska ju felet komma i "mainProgram" tycker jag.
Det var det som förbryllade mig (och irriterar fortfarande).
Tack för svar. Ifall du har kommentarer på detta läser jag dem gärna =)Sv: C# Throw exceptions från metoder (DLLer)
Om du inte hanterar ditt exception så bubblar det upp till runtime:n som hittar ett ohanterat exception och kommer fram till att det inte går att fortsätta utan måste terminera programmet. Innan den gör det bestämmer den sig för att visa litet felinformation för att ge litet ledtrådar till den stackare som skall felsöka programmet.
Det enda den då kan göra är att tala om var exceptionet kastades, dvs i dll:en. Hur skall den veta om det är felaktigheter i dll:en eller i exe:n som orsakade felet? det kunde ju ha varit 17 nivåer med dll:er emellan exe:n och dll:en. Hur skall rumtime:n avgöra vart felet orsakades? Det enda den kan göra är ju att presentera var felet skedde (eller snarare: var exceptionet kastades).
/AndreasSv:C# Throw exceptions från metoder (DLLer)
Eftersom jag har faktistk hanterat felet i MySQLHandler.dll; där catch:ar jag och sedan kastar jag felet. När jag kastar felet vill jag att den som anropade metoden ska få det felet jag kastar, och därför ska också felet "synas" i mitt "mainProgram". Det är ju (iaf som jag ser det) där ett unhandled exception faktiskt händer.
Mitt mainProgram får en Exception("FElet") kastat av metoden i MySQLHandler.dll. Om sedan mainProgram inte hanterar det - då får det mycket väl bli fel - men endast i mainProgram.
Det är ju inget fel i MySQLHandler.dll eftersom jag hanterade felet där. Således anser jag att det verkligen inte är ologiskt.
Tänker jag fel eller?Sv: C# Throw exceptions från metoder (DLLer)
Ja, men då kastar du ju felet i dll:en, alltså är det där felet uppstår.
<b>Det är ju inget fel i MySQLHandler.dll eftersom jag hanterade felet där.</b>
Det måhända att du hanterar InvalidCast-felet, men du kastar ju ett nytt!
Om du vill ha det som du säger få du nog returna en felkod, vilket du var inne på, och kasta exceptionen i huvudprogrammet istället. Du kanske kan göra om metoden så den kan returnera null vid fel.Sv:C# Throw exceptions från metoder (DLLer)
<code>
Object testObject = null;
Convert.ToInt32(testObject);
</code>
Felet kommer att kastas till det program/fil som kommer köra Convert.ToInt32. Om man inte catch:ar det där så får man InvalidCastException - inte i Convert.ToInt32().
Jag tycker inte det spelar någon roll att jag kastar ett nytt fel. Alltså, det är ju inget exception som jag ska hantera i MySQLHandler, det är ett Exception som ska hanteras någon annanstans. MySQLHandler vet ju att det "blev fel" och vil meddela detta till vem det nu var som kallade metoden. Precis som det fungerar över allt annars.
Att returnera null eller ett speciellt värde (i detta fallet någon double) är extremt fult och klumpigt tycker jag. Det betyder ju att jag för varje getDouble/getInt etc måste ha en if-sats som kontrollerar typ:
if (value == väldigtSpecielltVärde)
Verkligen dumt tycker jag...Sv: C# Throw exceptions från metoder (DLLer)
Ett annat exempel då det blir ännu mer påtagligt är trådhantering där man kan avbryta en tråd genom att anropa Thread.Abort (se http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemthreadingthreadclassaborttopic.asp) vilket orsakar ett ThreadAbortException på den tråden som man anropar det på. Dvs exceptionet (skumt ord, men jag vill undvika ordet undantag) orsakas av ett anrop i en annan tråd (som dessutom kommer att ha exekverat vidare och vara någon annan stans när exceptionet verkligen kastas). Hur skall runtimen kunna rapportera det korrekt? Återigen är det enda den kan göra att rapportera var exceptionet kastades.
Kom ihåg att det är primitiva saker vi pratar om här; datorer kan inte tänka :-).
/AndreasSv:C# Throw exceptions från metoder (DLLer)
Alltså, i mitt exempel ovan vet Convert-classen att mitt MainProgram anropade ToInt32(...). När sedan metoden ToInt32 kastar felet så kommer det fram till MainProgram precis som jag vill att det ska fungera.
Din fråga om hur Runtime vet vem det var är för mig lite konstig. Vem ska annars veta det lixom?