J'ai du code comme ci-dessous. J'utilise ma classe de connexion sql dans un bloc using . Lorsqu'il a terminé le travail, il supprime la connexion comme il est censé le faire. J'ai aussi quelques classes de noyau dans le même bloc using et je veux qu'elles soient éliminées lorsque le bloc using dans lequel elles se trouvent termine le travail.
J'ai cherché un peu mais je n'ai pas trouvé de réponse. Le bloc using supprime-t-il tous les objets qui se trouvent à l'intérieur de ses blocs ou se contente-t-il de supprimer l'objet qui a écrit comme paramètre? J'espère que j'ai demandé correctement. Je veux juste comprendre et je ne veux pas continuer à écrire des blocs inutiles.
using (SqlConnection conn = new SqlConnection("server=" + serverName + ";initial catalog=" +
dataBase + ";integrated security=false;uid=" +
sqlUser + ";password=" + sqlPass + ";"))
{
Kernel kernel = new Kernel();
Sirket sirket = default(Sirket);
Fatura fatura = default(Fatura);
try
{
sirket = kernel.yeniSirket(TVTTipi.vtMSSQL,
"vt adı",
"vt kull adı",
"vt kull sifre",
"netsis kull adı",
"netsis kull sifre",
sube kodu);
fatura = kernel.yeniFatura(sirket, TFaturaTip.ftSFat);
fatura.OkuUst("A00000000000011", "C0001");
fatura.OkuKalem();
fatura.kayitSil();
}
finally
{
Marshal.ReleaseComObject(fatura);// those are releasing the objects. if i didn't use those methods would they get disposed immediately as using block finishes.
Marshal.ReleaseComObject(sirket);
kernel.FreeNetsisLibrary();
Marshal.ReleaseComObject(kernel);
}
}
4 Réponses :
Non, using ne supprimera qu'un seul objet.
Cependant, l'utilisation de blocs imbriqués peut être écrite comme ceci:
class ComReleaseWrapper : IDisposable
{
object _obj;
public ComReleaseWrapper(object o) {
_obj = o;
}
public object Object { get { return _obj; } }
public void Dispose() {
if (_obj != null) {
Marshal.ReleaseComObject(_obj);
if (_obj is IDisposable d) d.Dispose();
}
_obj = null;
}
}
using (var kernelWrap = new ComReleaseWrapper(new Kernel()) {
var kernel = kernelWrap.Object as Kernel;
}
Remarque que les objets COM ne sont pas libérés avec using . Pour cela, vous avez besoin du bloc finally tel qu'il est écrit. Mettez simplement l'appel dispose là aussi.
Une alternative serait un wrapper, qui libère également l'objet COM. Plan:
using (var con = new SqlConnection())
using (var kernel = new Kernel())
{
// ...
} // Disposes kernel and con
Notez que noyau est un objet COM. OP fait Marshal.ReleaseComObject (noyau); . Comme Sinatr écrit correctement, il pourrait être enveloppé dans un IDisposable, cependant.
Vous avez raison, vous n'avez pas fait attention à cela ... Dans ce cas, je préférerais en fait le bloc finally avec élimination explicite s'il s'agit d'un cas d'utilisation unique. Sinon, une classe wrapper serait une bonne solution
Il ne dispose que de la variable définie comme dans ce cas serait SqlConnection . Si vous avez plusieurs éléments à éliminer, vous pouvez cependant les empiler comme suit pour que le code reste mieux lisible:
using (var f1 = new FileStream(@"C:\temp\file.txt", FileMode.Open))
using (var f2 = new FileStream(@"C:\temp\file.txt", FileMode.Open))
using (var f3 = new FileStream(@"C:\temp\file.txt", FileMode.Open))
{
//do stuff with filestreams here
}
Le bloc using ne supprime que l'objet initialisé entre parenthèses.
var conn = new SqlConnection(connectionString);
try
{
// Do all sort of stuff here with other disposable things
}
finally
{
// At this point in the code, only the SqlConnection gets disposed.
((IDisposable)conn).Dispose();
}
Le bloc using est du sucre syntaxique pour try ... finally - donc le code précédent est en fait traduit par ceci:
using (var conn = new SqlConnection(connectionString))
{
// Do all sort of stuff here with other disposable things
} // At this point in the code, only the SqlConnection gets disposed.
Non, il n'est pas nécessaire d'utiliser using inside using.
C'est un wrapper pour que nous n'ayons pas à supprimer explicitement l'objet.
plusieurs blocs en utilisant sont nécessaires, l'utilisation ne supprimera que le
IDisposableque vous mettez entre parenthèses: par exemple using (xxxx) - seul xxx est éliminé, rien d'autre à l'intérieur ne le fera, pour clarifier davantage, ma réponse concerne lesIDisposablesqui doivent être fermés, le GC normal fonctionnera sur les objets dans l'utilisation. Donc, par exemple, si dans votre connexion SQL, vous ouvrez unStream, vous devrez également le mettre dans unen utilisantDe plus, la déclaration using est une nouveauté avec C # 8. Il vous permet de déclarer une variable comme utilisant comme tel
en utilisant var conn = new SqlConnection (...);sans avoir de bloc using. Il supprimera alors automatiquement chaque variable déclarée comme celle-ci une fois que la variable sera hors de portée@MindSwipe mmm c # 8 ftw, j'aime ça
Veuillez noter qu'aucune des instances de l'instruction using n'est supprimée dans l'exemple de code de la question.
Disposen'est pas la même chose queMarshal.ReleaseComObject...La question est-elle: "Puis-je utiliser l'instruction
usingau lieu deMarshal.ReleaseComObject ()"? La réponse est non, mais vous pouvez facilement créer votre propre classe wrapper pour abuser (dans le bon sens) deIDisposableet y parvenir.