Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu öğreticide size .NET ve C# dilinde bir dizi özellik öğretildi. Şunları öğreneceksiniz:
- .NET CLI'nın temelleri
- C# Konsol Uygulamasının yapısı
- Konsol G/Ç
- .NET'teki Dosya G/Ç API'lerinin temelleri
- .NET'te Görev Tabanlı Zaman Uyumsuz Programlamanın temelleri
Metin dosyasını okuyan ve bu metin dosyasının içeriğini konsola yankılayan bir uygulama oluşturacaksınız. Konsol çıktısı, yüksek sesle okuma hızıyla uyumlu olacak şekilde ayarlanmıştır. '<' (küçüktür) veya '>' (büyüktür) tuşlarına basarak hızı hızlandırabilir veya yavaşlatabilirsiniz. Bu uygulamayı Windows, Linux, macOS veya bir Docker kapsayıcısında çalıştırabilirsiniz.
Bu öğreticide birçok özellik vardır. Şimdi bunları tek tek oluşturalım.
Önkoşullar
- En son .NET SDK
- Visual Studio Code düzenleyici
- C# Geliştirme Kiti
Uygulamayı oluşturma
İlk adım yeni bir uygulama oluşturmaktır. Bir komut istemi açın ve uygulamanız için yeni bir dizin oluşturun. Bunu geçerli dizin yapın. Komut istemine komut dotnet new console
yazın. Bu, temel bir "Merhaba Dünya" uygulaması için başlangıç dosyalarını oluşturur.
Değişiklik yapmaya başlamadan önce basit Hello World uygulamasını çalıştıralım. Uygulamayı oluşturduktan sonra komut istemine dotnet run
yazın. Bu komut NuGet paketi geri yükleme işlemini çalıştırır, uygulama yürütülebilir dosyasını oluşturur ve yürütülebilir dosyayı çalıştırır.
Basit Hello World uygulama kodunun tümü Program.csiçindedir. Bu dosyayı sık kullandığınız metin düzenleyiciyle açın. Program.cs içindeki kodu aşağıdaki kodla değiştirin:
namespace TeleprompterConsole;
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
Dosyanın üst kısmında bir namespace
ifadesine bakın. C#, kullanmış olabileceğiniz diğer Nesne Odaklı diller gibi türleri düzenlemek için ad alanlarını kullanır. Bu Hello World programı farklı değildir. Programın ad alanında TeleprompterConsole
adlı olduğunu görebilirsiniz.
Dosyayı Okuma ve Yansıtma
Eklenecek ilk özellik, bir metin dosyasını okuyup tüm bu metni konsolda görüntüleyebilmektir. İlk olarak bir metin dosyası ekleyelim. Bu örnek için GitHub deposundaki sampleQuotes.txt dosyasını proje dizininize kopyalayın. Bu, uygulamanız için komut dosyası işlevi görür. Bu öğretici için örnek uygulamayı indirme hakkında bilgi için Örnekler ve Öğreticileryönergelerine bakın.
Ardından, Program
sınıfınıza aşağıdaki yöntemi ekleyin (Main
yönteminin hemen altına):
static IEnumerable<string> ReadFrom(string file)
{
string? line;
using (var reader = File.OpenText(file))
{
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
Bu yöntem, yineleyici yöntemi olarak adlandırılan özel bir C# yöntemi türüdür. Yineleyici yöntemler, tembel bir şekilde değerlendirilen dizileri döndürür. Bu, dizideki her öğenin, sırayı kullanan kod tarafından istendiği şekilde oluşturulduğu anlamına gelir. Yineleyici yöntemleri, bir veya daha fazla yield return
deyimi içeren yöntemlerdir.
ReadFrom
yöntemi tarafından döndürülen nesnesi, dizideki her öğeyi oluşturmaya yönelik kodu içerir. Bu örnekte, kaynak dosyadan bir sonraki metin satırını okumayı ve bu dizeyi döndürmeyi içerir. Çağıran kod diziden bir sonraki öğeyi her istediğinde, kod dosyadan sonraki metin satırını okur ve döndürür. Dosya tamamen okunduğunda, sıra başka öğe olmadığını gösterir.
Sizin için yeni olabilecek iki C# söz dizimi öğesi vardır. Bu yöntemdeki using
deyimi kaynak temizlemeyi yönetir.
using
deyiminde başlatılan değişkenin (bu örnektereader
) IDisposable arabirimini uygulaması gerekir. Bu arabirim, kaynağın yayımlanması gerektiğinde çağrılması gereken tek bir yöntem (Dispose
) tanımlar. Derleyici, yürütme using
deyiminin kapanış küme ayracına ulaştığında bu çağrıyı oluşturur. Derleyici tarafından oluşturulan kod, using deyimi tarafından tanımlanan bloktaki koddan bir özel durum oluşturulsa bile kaynağın serbest bırakılmasını sağlar.
reader
değişkeni var
anahtar sözcüğü kullanılarak tanımlanır.
var
, örtük olarak yazılan biryerel değişken tanımlar. Bu, değişkenin türünün değişkene atanan nesnenin derleme zamanı türüne göre belirlendiği anlamına gelir. Burada, OpenText(String) yönteminden döndürülen değer, StreamReader nesnesidir.
Şimdi Main
yöntemindeki dosyayı okumak için kodu dolduralım:
var lines = ReadFrom("sampleQuotes.txt");
foreach (var line in lines)
{
Console.WriteLine(line);
}
Programı çalıştırın (dotnet run
kullanarak) ve konsola yazdırılan her satırı görebilirsiniz.
Çıkışa gecikmeler ekleme ve biçimlendirme
Elinizdeki şey, yüksek sesle okunamayacak kadar hızlı görüntüleniyor. Şimdi çıkıştaki gecikmeleri eklemeniz gerekir. Başlarken, zaman uyumsuz işlemeyi etkinleştiren çekirdek kodlardan bazılarını oluşturacaksınız. Ancak, bu ilk adımlar birkaç karşı-desen izler. Koda ekleme yapılırken anti-desens yorumlarda belirtilir ve kod sonraki adımlarda güncellenir.
Bu bölümün iki adımı vardır. İlk olarak, yineleyici yöntemini satırların tamamı yerine tek sözcükler döndürecek şekilde güncelleştireceksiniz. Bu değişikliklerle tamamlandı.
yield return line;
deyimini aşağıdaki kodla değiştirin:
var words = line.Split(' ');
foreach (var word in words)
{
yield return word + " ";
}
yield return Environment.NewLine;
Ardından, dosyanın satırlarını kullanma şeklinizi değiştirmeniz ve her sözcüğü yazdıktan sonra bir gecikme eklemeniz gerekir.
Main
yöntemindeki Console.WriteLine(line)
deyimini aşağıdaki blokla değiştirin:
Console.Write(line);
if (!string.IsNullOrWhiteSpace(line))
{
var pause = Task.Delay(200);
// Synchronously waiting on a task is an
// anti-pattern. This will get fixed in later
// steps.
pause.Wait();
}
Örneği çalıştırın ve çıktıyı denetleyin. Şimdi, her bir sözcük yazdırılır ve ardından 200 ms gecikme olur. Ancak, kaynak metin dosyasında satır sonu olmadan 80'den fazla karakter içeren birkaç satır olduğundan, görüntülenen çıktı bazı sorunları gösterir. Kaydırılırken bunu okumak zor olabilir. Bunu düzeltmek kolay. Yalnızca her satırın uzunluğunu takip eder ve çizgi uzunluğu belirli bir eşiğe ulaştığında yeni bir çizgi oluşturursunuz. satır uzunluğunu tutan ReadFrom
yönteminde words
bildiriminden sonra yerel bir değişken bildirin:
var lineLength = 0;
Ardından, yield return word + " ";
deyiminden sonra (kapanış ayracından önce) aşağıdaki kodu ekleyin:
lineLength += word.Length + 1;
if (lineLength > 70)
{
yield return Environment.NewLine;
lineLength = 0;
}
Örneği çalıştırdığınızda, önceden yapılandırılmış hızıyla yüksek sesle okuyabileceksiniz.
Eş Zamansız Görevler
Bu son adımda, çıktıyı bir göreve zaman uyumsuz olarak yazmak için kodu eklerken, metin görünümünü hızlandırmak veya yavaşlatmak ya da metin görünümünü tamamen durdurmak isteyen kullanıcıdan gelen girişleri okumak için başka bir görev çalıştıracaksınız. Bu işlemde birkaç adım vardır ve sonunda ihtiyacınız olan tüm güncelleştirmelere sahip olursunuz. İlk adım, dosyayı okumak ve görüntülemek için şu ana kadar oluşturduğunuz kodu temsil eden zaman uyumsuz Task dönüş yöntemi oluşturmaktır.
Bu yöntemi Program
sınıfınıza ekleyin (Main
yönteminizin gövdesinden alınır):
private static async Task ShowTeleprompter()
{
var words = ReadFrom("sampleQuotes.txt");
foreach (var word in words)
{
Console.Write(word);
if (!string.IsNullOrWhiteSpace(word))
{
await Task.Delay(200);
}
}
}
İki değişiklik fark edeceksiniz. İlk olarak, yöntemin gövdesinde, bir görevin zaman uyumlu bir şekilde bitmesini beklemek için Wait() çağırmak yerine, bu sürüm await
anahtar sözcüğünü kullanır. Bunu yapmak için yöntem imzasına async
değiştiricisini eklemeniz gerekir. Bu yöntem bir Task
döndürür.
Task
nesnesi döndüren herhangi bir dönüş ifadisi olmadığını fark edin. Bunun yerine, bu Task
nesnesi, await
işlecini kullandığınızda derleyicinin oluşturduğu kodla oluşturulur. Bu yöntem bir await
'a ulaştığında geri döner diye düşünebilirsiniz. Döndürülen Task
, çalışmanın tamamlanmadığını gösterir. Beklenen görev tamamlandığında yöntemi sürdürülür. Tamamlanmaya kadar yürütülürken, döndürülen Task
işlemin tamamlandığını gösterir.
Çağrı kodu, döndürülen Task
değerini izleyerek ne zaman bitirdiğini belirleyebilir.
ShowTeleprompter
çağrısından önce bir await
anahtar sözcüğü ekleyin:
await ShowTeleprompter();
Bunun için Main
yöntemi imzasını şu şekilde değiştirmeniz gerekir:
static async Task Main(string[] args)
temel bilgiler bölümümüzde async Main
yöntemi hakkında daha fazla bilgi edinin.
Ardından, Konsoldan okumak için ikinci zaman uyumsuz yöntemi yazmanız ve '<' (küçüktür), '>' (büyüktür) ve 'X' veya 'x' anahtarlarını izlemeniz gerekir. Bu görev için eklediğiniz yöntem şu şekildedir:
private static async Task GetInput()
{
var delay = 200;
Action work = () =>
{
do {
var key = Console.ReadKey(true);
if (key.KeyChar == '>')
{
delay -= 10;
}
else if (key.KeyChar == '<')
{
delay += 10;
}
else if (key.KeyChar == 'X' || key.KeyChar == 'x')
{
break;
}
} while (true);
};
await Task.Run(work);
}
Bu, Konsoldan bir anahtar okuyan ve kullanıcı '<' (küçüktür) veya '>' (büyüktür) tuşlarına bastığında gecikmeyi temsil eden yerel değişkeni değiştiren Action temsilcisini temsil eden bir lambda ifadesi oluşturur. Temsilci yöntemi, kullanıcı 'X' veya 'x' tuşlarına bastığında tamamlar ve bu da kullanıcının metin görüntüsünü istediği zaman durdurmasına olanak tanır. Bu yöntem, kullanıcının bir tuşa basmasını engellemek ve beklemek için ReadKey() kullanır.
Bu özelliği tamamlamak için, bu görevlerin her ikisini de (GetInput
ve ShowTeleprompter
) başlatan ve bu iki görev arasındaki paylaşılan verileri yöneten yeni bir async Task
dönüş yöntemi oluşturmanız gerekir.
Bu iki görev arasındaki paylaşılan verileri işleyebilen bir sınıf oluşturmanın zamanı geldi. Bu sınıf iki genel özellik içerir: gecikme ve dosyanın tamamen okunduğunu belirten bir bayrak Done
:
namespace TeleprompterConsole;
internal class TelePrompterConfig
{
public int DelayInMilliseconds { get; private set; } = 200;
public void UpdateDelay(int increment) // negative to speed up
{
var newDelay = Min(DelayInMilliseconds + increment, 1000);
newDelay = Max(newDelay, 20);
DelayInMilliseconds = newDelay;
}
public bool Done { get; private set; }
public void SetDone()
{
Done = true;
}
}
Bu sınıfı yeni bir dosyaya yerleştirin ve bu sınıfı gösterildiği gibi TeleprompterConsole
ad alanına ekleyin. Ayrıca, kapsayan sınıf veya ad alanı adları olmadan Min
ve Max
yöntemlerine başvurabilmeniz için dosyanın en üstüne bir using static
deyimi eklemeniz gerekir.
using static
deyimi, yöntemleri bir sınıftan içeri aktarır. Bu, static
içermeyen ve ad alanından tüm sınıfları içeri aktaran using
deyiminin aksinedir.
using static System.Math;
Ardından, yeni config
nesnesini kullanmak için ShowTeleprompter
ve GetInput
yöntemlerini güncelleştirmeniz gerekir. Her iki görevi de başlatmak ve ilk görev tamamlandığında çıkmak için async
yöntemini döndüren son bir Task
yazın:
private static async Task RunTeleprompter()
{
var config = new TelePrompterConfig();
var displayTask = ShowTeleprompter(config);
var speedTask = GetInput(config);
await Task.WhenAny(displayTask, speedTask);
}
Buradaki yeni yöntemlerden biri WhenAny(Task[]) çağrısıdır. Bu, argüman listesindeki görevlerden herhangi biri tamamlandığında sona eren bir Task
oluşturur.
Ardından, gecikme için config
nesnesini kullanmak için hem ShowTeleprompter
hem de GetInput
yöntemlerini güncelleştirmeniz gerekir:
private static async Task ShowTeleprompter(TelePrompterConfig config)
{
var words = ReadFrom("sampleQuotes.txt");
foreach (var word in words)
{
Console.Write(word);
if (!string.IsNullOrWhiteSpace(word))
{
await Task.Delay(config.DelayInMilliseconds);
}
}
config.SetDone();
}
private static async Task GetInput(TelePrompterConfig config)
{
Action work = () =>
{
do {
var key = Console.ReadKey(true);
if (key.KeyChar == '>')
config.UpdateDelay(-10);
else if (key.KeyChar == '<')
config.UpdateDelay(10);
else if (key.KeyChar == 'X' || key.KeyChar == 'x')
config.SetDone();
} while (!config.Done);
};
await Task.Run(work);
}
bu yeni ShowTeleprompter
sürümü, TeleprompterConfig
sınıfında yeni bir yöntem çağırır. Şimdi ShowTeleprompter
yerine RunTeleprompter
çağırmak için Main
güncelleştirmeniz gerekir:
await RunTeleprompter();
Sonuç
Bu öğreticide, Konsol uygulamalarında çalışmayla ilgili C# dili ve .NET Core kitaplıkları ile ilgili bir dizi özellik gösterilmiştir. Dil ve burada tanıtılan sınıflar hakkında daha fazla bilgi edinmek için bu bilgiyi temel alabilirsiniz. Dosya ve Konsol G/Ç'nin temellerini, Görev tabanlı zaman uyumsuz programlamanın engelleyen ve engellemeyen kullanımını, C# diline yönelik bir turu, C# programlarının nasıl organize edildiğini ve .NET CLI'yi gördünüz.
Dosya G/Ç hakkında daha fazla bilgi için bkz. Dosya ve Akım G/Ç. Bu öğreticide kullanılan zaman uyumsuz programlama modeli hakkında daha fazla bilgi için bkz. Görev Tabanlı Zaman Uyumsuz Programlama ve Zaman Uyumsuz programlama.