Użytkownik kokos odpowiedział na cudowne Ukryte funkcje pytania C # , podając using
słowo kluczowe. Czy możesz to rozwinąć? Jakie są zastosowania using
?
Użytkownik kokos odpowiedział na cudowne Ukryte funkcje pytania C # , podając using
słowo kluczowe. Czy możesz to rozwinąć? Jakie są zastosowania using
?
Odpowiedzi:
Powodem tego using
stwierdzenia jest upewnienie się, że obiekt jest usuwany, gdy tylko znajdzie się poza zasięgiem, i nie wymaga jawnego kodu, aby mieć pewność, że tak się stanie.
Podobnie jak w Zrozumienie instrukcji „using” w języku C # (projekt kodu) i Korzystanie z obiektów, które implementują IDisposable (Microsoft) , kompilator C # konwertuje
using (MyResource myRes = new MyResource())
{
myRes.DoSomething();
}
do
{ // Limits scope of myRes
MyResource myRes= new MyResource();
try
{
myRes.DoSomething();
}
finally
{
// Check for a null resource.
if (myRes != null)
// Call the object's Dispose method.
((IDisposable)myRes).Dispose();
}
}
C # 8 wprowadza nową składnię o nazwie „ using declarations ”:
Deklaracja użycia to deklaracja zmiennej poprzedzona słowem kluczowym using. Mówi kompilatorowi, że deklarowana zmienna powinna zostać umieszczona na końcu otaczającego zakresu.
Więc równoważny kod powyższy byłby:
using var myRes = new MyResource();
myRes.DoSomething();
A gdy kontrola opuści zawarty zakres (zwykle jest to metoda, ale może to być również blok kodu), myRes
zostanie usunięta.
using
upewnia się, że Dispose
jest wywoływane, gdy skończysz z obiektem.
MyRessource
jest strukturą. Oczywiście nie ma testu na nieważność, ale również nie ma możliwości boksowania IDisposable
. Emitowane jest ograniczone połączenie wirtualne.
using
zmiennej, wbudowana w nią zmienna jest tylko do odczytu. Nie ma sposobu na osiągnięcie tego dla zmiennych lokalnych bez using
instrukcji.
Ponieważ wiele osób nadal:
using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
//code
}
Myślę, że wiele osób wciąż nie wie, że możesz to zrobić:
using (System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader("")) {
//code
}
Takie rzeczy:
using (var conn = new SqlConnection("connection string"))
{
conn.Open();
// Execute SQL statement here on the connection you created
}
To SqlConnection
będzie zamknięty bez konieczności jawnie wywołać .Close()
funkcję, a stanie się to nawet jeśli jest wyjątek , bez konieczności dotyczący try
/ catch
/ finally
.
return
w środku using
bloku.
za pomocą, w sensie
using (var foo = new Bar())
{
Baz();
}
Jest tak naprawdę skrótem dla bloku try / wreszcie. Jest to równoważne z kodem:
var foo = new Bar();
try
{
Baz();
}
finally
{
foo.Dispose();
}
Zauważysz oczywiście, że pierwszy fragment jest znacznie bardziej zwięzły niż drugi, a także, że istnieje wiele rodzajów rzeczy, które możesz zrobić jako czyszczenie, nawet jeśli zostanie zgłoszony wyjątek. Z tego powodu stworzyliśmy klasę, którą nazywamy Scope, która pozwala na wykonanie dowolnego kodu w metodzie Dispose. Na przykład, jeśli masz właściwość IsWorking, którą zawsze chciałeś ustawić na false po próbie wykonania operacji, zrobiłbyś to w ten sposób:
using (new Scope(() => IsWorking = false))
{
IsWorking = true;
MundaneYetDangerousWork();
}
Możesz przeczytać więcej o naszym rozwiązaniu i sposobie jego uzyskania tutaj .
Dokumentacja Microsoft stwierdza, że używanie ma podwójną funkcję ( https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx ), zarówno jako dyrektywę, jak i w instrukcjach . Jako stwierdzenie , jak wskazano tutaj w innych odpowiedziach, słowem kluczowym jest cukier składniowy w celu ustalenia zakresu dysponowania obiektem IDisposable . Jako dyrektywa jest rutynowo używana do importowania przestrzeni nazw i typów. Również jako dyrektywę możesz tworzyć aliasy dla przestrzeni nazw i typów, jak wskazano w książce „C # 5.0 In a Nutshell: The Definitive Guide” ( http://www.amazon.com/5-0-Nutshell-The- Definitive-Reference-ebook / dp / B008E6I1K8), Joseph i Ben Albahari. Jeden przykład:
namespace HelloWorld
{
using AppFunc = Func<IDictionary<DateTime, string>, List<string>>;
public class Startup
{
public static AppFunc OrderEvents()
{
AppFunc appFunc = (IDictionary<DateTime, string> events) =>
{
if ((events != null) && (events.Count > 0))
{
List<string> result = events.OrderBy(ev => ev.Key)
.Select(ev => ev.Value)
.ToList();
return result;
}
throw new ArgumentException("Event dictionary is null or empty.");
};
return appFunc;
}
}
}
Jest to coś, co należy mądrze zastosować, ponieważ nadużywanie tej praktyki może zaszkodzić przejrzystości kodu. Jest ładne wyjaśnienie na temat aliasów C #, wymieniając również zalety i wady, w DotNetPearls ( http://www.dotnetperls.com/using-alias ).
using
jako narzędzia aliasu. To dezorientuje mnie podczas czytania kodu - już wiem, że System.Collections
istnieje i ma IEnumerable<T>
klasę. Używanie aliasu, aby nazwać to czymś innym, zaciemnia to dla mnie. Widzę using FooCollection = IEnumerable<Foo>
jako sposób na to, aby późniejsi programiści przeczytali kod i pomyśleli: „Co to do diabła jest FooCollection
i dlaczego nie ma gdzieś klasy?” Nigdy go nie używam i odradzałbym jego użycie. Ale to może być tylko ja.
W przeszłości często go używałem do pracy ze strumieniami wejściowymi i wyjściowymi. Możesz je ładnie zagnieździć, a to eliminuje wiele potencjalnych problemów, na które zwykle napotykasz (automatycznie wywołując dispose). Na przykład:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (System.IO.StreamReader sr = new StreamReader(bs))
{
string output = sr.ReadToEnd();
}
}
}
Dodanie czegoś, co mnie zaskoczyło, nie pojawiło się. Najbardziej interesującą cechą używania (moim zdaniem) jest to, że bez względu na to, jak wyjdziesz z używanego bloku, zawsze pozbywa się on obiektu. Obejmuje to zwroty i wyjątki.
using (var db = new DbContext())
{
if(db.State == State.Closed) throw new Exception("Database connection is closed.");
return db.Something.ToList();
}
Nie ma znaczenia, czy wyjątek zostanie zgłoszony, czy lista zostanie zwrócona. Obiekt DbContext zawsze będzie usuwany.
Innym doskonałym zastosowaniem use jest tworzenie instancji modalnego okna dialogowego.
Using frm as new Form1
Form1.ShowDialog
' do stuff here
End Using
Podsumowując, kiedy używasz zmiennej lokalnej typu, która implementuje IDisposable
, zawsze bez wyjątku używaj using
1 .
Jeśli używasz IDisposable
zmiennych nielokalnych , zawsze implementuj IDisposable
wzorzec .
Dwie proste zasady, bez wyjątku 1 . W przeciwnym razie zapobieganie wyciekom zasobów jest prawdziwym problemem.
1) : Jedynym wyjątkiem jest - gdy zajmujesz się wyjątkami. Może wtedy być mniej kodu do Dispose
jawnego wywołania w finally
bloku.
Możesz skorzystać z przestrzeni nazw aliasu w następujący sposób:
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
Nazywa się to dyrektywą aliasową, jak widać, można ją wykorzystać do ukrycia od dawna odwoływanych referencji, jeśli chcesz, aby w kodzie było oczywiste, do czego się odwołujesz np.
LegacyEntities.Account
zamiast
CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account
lub po prostu
Account // It is not obvious this is a legacy entity
Co ciekawe, możesz również użyć wzorca using / IDisposable do innych interesujących rzeczy (takich jak inny sposób, w jaki używa go Rhino Mocks). Zasadniczo możesz skorzystać z faktu, że kompilator zawsze wywoła funkcję .Dispozycjonuje na „używanym” obiekcie. Jeśli masz coś, co musi się wydarzyć po określonej operacji ... coś, co ma określony początek i koniec ... to możesz po prostu stworzyć IDisposable klasę, która rozpoczyna operację w konstruktorze, a następnie kończy się w metodzie Dispose.
Pozwala to na użycie naprawdę miłej składni przy oznaczaniu wyraźnego początku i końca tej operacji. Tak działa również funkcja System.Transactions.
Korzystając z ADO.NET, możesz użyć klucza do takich rzeczy, jak obiekt połączenia lub obiekt czytnika. W ten sposób, gdy blok kodu zostanie ukończony, automatycznie pozbędzie się twojego połączenia.
„using” może także służyć do rozwiązywania konfliktów przestrzeni nazw. Zobacz http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ dla krótkiego samouczka, który napisałem na ten temat.
public class ClassA:IDisposable
{
#region IDisposable Members
public void Dispose()
{
GC.SuppressFinalize(this);
}
#endregion
}
public void fn_Data()
{
using (ClassA ObjectName = new ClassA())
{
//use objectName
}
}
użycie jest używane, gdy masz zasób, który chcesz pozbyć się po jego użyciu.
Na przykład, jeśli alokujesz zasób pliku i potrzebujesz go użyć tylko w jednej sekcji kodu do krótkiego czytania lub pisania, użycie jest pomocne w usuwaniu zasobu pliku, gdy tylko to zrobisz.
Używany zasób musi zaimplementować IDisposable, aby działać poprawnie.
Przykład:
using (File file = new File (parameters))
{
*code to do stuff with the file*
}
Słowo kluczowe using definiuje zakres obiektu, a następnie usuwa obiekt po zakończeniu zakresu. Na przykład.
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
Zobacz tutaj artykuł MSDN na temat C # za pomocą słowa kluczowego.
Nie jest to bardzo ważne, ale można go również używać do zmiany zasobów w locie. Tak, jednorazowe, jak wspomniano wcześniej, ale być może nie chcesz, aby zasoby były niezgodne z innymi zasobami podczas reszty egzekucji. Więc chcesz się go pozbyć, aby nie ingerował gdzie indziej.
Dzięki komentarzom poniżej trochę posprzątam ten post (nie powinienem wtedy używać słów „odśmiecanie”, przepraszam):
Gdy użyjesz, wywoła metodę Dispose () na obiekcie na końcu zakresu użycia. Więc możesz mieć całkiem niezły kod czyszczenia w metodzie Dispose ().
Punkt kulisty tutaj, który, mam nadzieję, może uzyskać to niezaznaczone: Jeśli zaimplementujesz IDisposable, upewnij się, że wywołujesz GC.SuppressFinalize () w implementacji Dispose (), ponieważ w przeciwnym razie nastąpi automatyczne odśmiecanie i finalizacja go w pewnym momencie punkt, który przynajmniej byłby marnotrawstwem zasobów, jeśli już go pozbyłeś () d.
Kolejny przykład racjonalnego wykorzystania, w którym obiekt jest natychmiast usuwany:
using (IDataReader myReader = DataFunctions.ExecuteReader(CommandType.Text, sql.ToString(), dp.Parameters, myConnectionString))
{
while (myReader.Read())
{
MyObject theObject = new MyObject();
theObject.PublicProperty = myReader.GetString(0);
myCollection.Add(theObject);
}
}
Wszystko poza nawiasami klamrowymi jest usuwane, więc świetnie jest pozbyć się przedmiotów, jeśli ich nie używasz. Dzieje się tak, ponieważ jeśli masz obiekt SqlDataAdapter i używasz go tylko raz w cyklu życia aplikacji i wypełniasz tylko jeden zestaw danych, a nie potrzebujesz go już, możesz użyć kodu:
using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
// do stuff
} // here adapter_object is disposed automatically
Instrukcja using zapewnia mechanizm wygody do prawidłowego używania obiektów IDisposable. Z reguły, gdy używasz obiektu IDisposable, powinieneś zadeklarować go i utworzyć jego instancję w instrukcji using. Instrukcja using wywołuje metodę Dispose na obiekcie we właściwy sposób i (gdy używasz go, jak pokazano wcześniej), powoduje on również, że sam obiekt wykracza poza zasięg natychmiast po wywołaniu Dispose. W używanym bloku obiekt jest tylko do odczytu i nie można go modyfikować ani ponownie przypisywać.
To pochodzi z: tutaj
Można go również wykorzystać do tworzenia zakresów na przykład:
class LoggerScope:IDisposable {
static ThreadLocal<LoggerScope> threadScope =
new ThreadLocal<LoggerScope>();
private LoggerScope previous;
public static LoggerScope Current=> threadScope.Value;
public bool WithTime{get;}
public LoggerScope(bool withTime){
previous = threadScope.Value;
threadScope.Value = this;
WithTime=withTime;
}
public void Dispose(){
threadScope.Value = previous;
}
}
class Program {
public static void Main(params string[] args){
new Program().Run();
}
public void Run(){
log("something happend!");
using(new LoggerScope(false)){
log("the quick brown fox jumps over the lazy dog!");
using(new LoggerScope(true)){
log("nested scope!");
}
}
}
void log(string message){
if(LoggerScope.Current!=null){
Console.WriteLine(message);
if(LoggerScope.Current.WithTime){
Console.WriteLine(DateTime.Now);
}
}
}
}
Instrukcja using mówi .NET, aby zwolnił obiekt określony w bloku using, gdy nie jest już potrzebny. Dlatego powinieneś użyć bloku „using” dla klas, które wymagają czyszczenia po nich, takich jak Typy System.IO.
Istnieją dwa sposoby użycia tego using
słowa kluczowego w języku C # w następujący sposób.
Jako dyrektywa
Zasadniczo używamy using
słowa kluczowego, aby dodawać przestrzenie nazw w plikach kodu i klasach. Następnie udostępnia wszystkie klasy, interfejsy i klasy abstrakcyjne oraz ich metody i właściwości na bieżącej stronie.
Przykład:
using System.IO;
Jako oświadczenie
Jest to inny sposób użycia using
słowa kluczowego w języku C #. Odgrywa istotną rolę w poprawie wydajności w Garbage Collection.
Do using
rachunku zapewnia, że Dispose () jest wywoływana nawet jeśli wystąpi wyjątek podczas tworzenia obiektów i wywoływanie metod, właściwości i tak dalej. Dispose () to metoda obecna w interfejsie IDisposable, która pomaga zaimplementować niestandardowe czyszczenie pamięci. Innymi słowy, jeśli wykonuję jakieś operacje na bazie danych (Wstaw, Aktualizuj, Usuń), ale jakoś występuje wyjątek, to tutaj instrukcja using zamyka połączenie automatycznie. Nie trzeba jawnie wywoływać metody Close () połączenia.
Innym ważnym czynnikiem jest to, że pomaga w tworzeniu puli połączeń. Pula połączeń w .NET pomaga wielokrotnie eliminować zamykanie połączenia z bazą danych. Wysyła obiekt połączenia do puli do wykorzystania w przyszłości (następne wywołanie bazy danych). Przy następnym wywołaniu połączenia z bazą danych z aplikacji pula połączeń pobiera obiekty dostępne w puli. Pomaga to poprawić wydajność aplikacji. Kiedy więc używamy instrukcji using, kontroler wysyła obiekt do puli połączeń automatycznie, nie ma potrzeby jawnego wywoływania metod Close () i Dispose ().
Możesz zrobić to samo, co robi instrukcja using, używając bloku try-catch i wywołać jawnie funkcję Dispose () w ostatnim bloku. Ale instrukcja using wykonuje wywołania automatycznie, aby kod był czystszy i bardziej elegancki. W używanym bloku obiekt jest tylko do odczytu i nie można go modyfikować ani ponownie przypisywać.
Przykład:
string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";
conn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));
}
}
W poprzednim kodzie nie zamykam żadnego połączenia; zamknie się automatycznie. using
Oświadczenie wezwie conn.Close () automatycznie ze względu na using
rachunku ( using (SqlConnection conn = new SqlConnection(connString)
) i taka sama dla obiektu SqlDataReader. A także jeśli wystąpi jakiś wyjątek, połączenie zostanie automatycznie zamknięte.
Aby uzyskać więcej informacji, zobacz Wykorzystanie i znaczenie używania w języku C # .
Rhino Mocks Record-odtwarzanie Składnia sprawia ciekawą wykorzystanie using
.
użycie jako instrukcji automatycznie wywołuje dispose na określonym obiekcie. Obiekt musi implementować interfejs IDisposable. Możliwe jest użycie kilku obiektów w jednej instrukcji, o ile są one tego samego typu.
CLR konwertuje kod na MSIL. A instrukcja using zostaje przetłumaczona na try i wreszcie blok. W ten sposób instrukcja using jest reprezentowana w IL. Instrukcja użytkowania jest tłumaczona na trzy części: nabywanie, użytkowanie i usuwanie. Najpierw pozyskiwany jest zasób, a następnie użycie jest ujęte w instrukcji try z klauzulą final. Obiekt zostaje następnie umieszczony w klauzuli ostatecznie.
Użycie klauzuli służy do zdefiniowania zakresu dla konkretnej zmiennej. Na przykład:
Using(SqlConnection conn=new SqlConnection(ConnectionString)
{
Conn.Open()
// Execute sql statements here.
// You do not have to close the connection explicitly here as "USING" will close the connection once the object Conn becomes out of the defined scope.
}