Bu kodda ne yanlış var? – 8

Çalıştığımız proje’de, aşağıda tanımı verilmiş struct‘tan 1000 tane üretip geri döndüren bir fonksiyon yazmamız gerekiyor;

struct Boyut { public int Genislik; public int Yukseklik; }

Proje Liderine yazdığımız kodu gösteriyoruz. Kod çalışırken hiçbir hata üretmemesine rağmen, kodu değiştirmemizi istiyor.

private Boyut[] BoyutlarListesi() { Boyut[] boyutlar = new Boyut[1000];

for (int iLoop = 0; iLoop < boyutlar.Length; iLoop++)
{
    boyutlar[iLoop] = new Boyut();
}

return boyutlar; }

Sizce neden böyle bir istekte bulunmuş olabilir?

İpucu : Proje Lideri performans takıntısı olan eski bir programcı

C# ile LINQ filtrelerinin üç farklı kullanımı (Predicate Function, Anonymous Method, Lambda Expression)

Listeler (IEnumerable<T> interface‘ini implemente eden) üzerinde filtreleme yapmak için .Net 3.0‘dan beri LINQ sorgularını kullanabiliyoruz.

LINQ ile gelen farklı operatör grupları sayesinde, listeler üzerinde sadece filtreleme yapmanın ötesinde bir kontrolümüz oluyor (daha detaylı bilgi için MSDN’de yeralan The .Net Standard Query Operators makalesini okuyabilirsiniz);

Bu yazımda, bir liste uzerinde LINQ sorgusu gerçekleştirmenin 3 farklı yolunu inceleyeceğiz;

  • Predicate
  • Anonymous Method
  • Lambda Sorgusu

Öncelikle üzerinde çalışacağımız bir listeye ihtiyacımız olacak, Enumerable sınıfının static Range method’u ile iki değer aralığındaki tam sayılardan oluşan listeyi kullanabiliriz;

Predicate

Sonuç;

LINQ Sorgusu - Predicate Function

Anonymous Method

LINQ Sorgusu - Anonymous Method

Lambda Sorgusu

LINQ Sorgusu - Lambda Expression

XNA Oyunu / Çanakkale Geçilmez - 1

Bu yazımı okumadan önce XNA konusundaki diğer makalelerimi okumanızı öneririm.

Bu sefer yapacağımız oyun, 30 Ağustos‘un ruhuna uygun olacak - Çanakkale Geçilmez.

Önce görsellerimizi verelim;

XNA - Çanakkale Geçilmez - Arkaplan XNA - Çanakkale Geçilmez - Düşman Gemisi XNA - Çanakkale Geçilmez - Top XNA - Çanakkale Geçilmez - Gülle XNA - Çanakkale Geçilmez - Karakterler XNA - Çanakkale Geçilmez - Sayılar

İki tane de ses dosyamız var;

Gemi Vuruldu Sesi

Arkaplan Müziği

Başlayalım oyunumuzu yazmaya; Çanakkale Geçilmez projemizi oluşturduktan ve Game1.cs‘in ismini GameLoop.cs olarak değiştirdikten sonra, class seviyesindeki değişkenlerimizi tanımlayalım;

public const int PENCERE_GENISLIK = 800; public const int PENCERE_YUKSEKLIK = 600; public const bool TAM_EKRAN = false;

Texture2D Arkaplan;</pre>

Oyun penceremizin sınırlarını tutacağımız Rectangle tipinde bir değişkeni class seviyesindeki değişkenlerimize ekleyelim;

Rectangle Pencere;

Gelelim bu değişkenleri kullanmaya, GameLoop class‘ımızın constructor methodunda aşağıdaki kodları yazalım;

graphics.PreferredBackBufferWidth = PENCERE_GENISLIK;
graphics.PreferredBackBufferHeight = PENCERE_YUKSEKLIK;
graphics.IsFullScreen = TAM_EKRAN;
Pencere = new Rectangle(0, 0, PENCERE_GENISLIK, PENCERE_YUKSEKLIK);

Ses dosyalarımız için class seviyesinde değişkenlerimiz tanımlayalım;

SoundEffectInstance ArkaplanSes;
SoundEffectInstance GemiVurulduSes;

LoadContent() method‘unda değişkenlerimize yükleme işlemlerini gerçekleştirelim;

Arkaplan = Content.Load<Texture2D>("Arkaplan");

ArkaplanSes = Content.Load<SoundEffect>("pong").CreateInstance();
GemiVurulduSes = Content.Load<SoundEffect>("ir_begin").CreateInstance();

ArkaplanSes.IsLooped = true;
ArkaplanSes.Volume = 0.3f;
ArkaplanSes.Play();

Ses dosyaları ile yaptığımız bu işlemleri XNA ile Pong oyunu yazalım – 2 yazımdan hatırlayacaksınız.

Bu oyunumuzda aktörleri Nesne Yönelimli Programlama (Object Orriented Programming) kurallarına uyarak oluşturalım; oyun projemize yeni bir class ekleyelim ve ismini GameObject.cs verelim.

Çanakkale Geçilmez oyunumuzda oluşturacağımız tüm nesneleri GameObject class’ından oluşturacağız.

public class GameObject
{
    public bool IsAlive;
    public Texture2D Texture;
    public Vector2 Position;
    public Vector2 Center;
    public Vector2 Velocity;
    public float Rotation;

    private Rectangle _TextureRectangle;
    public Rectangle TextureRectangle
    {
        get
        {
            _TextureRectangle.X = (int)Position.X;
            _TextureRectangle.Y = (int)Position.Y;

            return _TextureRectangle;
        }
    }

    public GameObject(Texture2D Texture)
    {
        this.IsAlive = false;
        this.Texture = Texture;
        this.Center = new Vector2(Texture.Width / 2, Texture.Height / 2);
        this.Position = Vector2.Zero;
        this.Velocity = Vector2.Zero;
        this.Rotation = 0;

        this._TextureRectangle = new Rectangle(0, 0, Texture.Width, Texture.Height);
    }
}

Yukarıdaki kodu incelediğimizde;

  • Oyun nesnesinin hala canlı olup olmadığını anlamak için IsAlive değişkeninin olduğunu
  • Oyun nesnesinin Texture‘unu almak için Texture nesnesinin olduğunu
  • Oyun nesnesinin ekrandaki yerini almak için Position değişkeninin olduğunu
  • Oyun nesnesinin kendi etrafında dönüş miktarını almak için Center ve Rotation değişkenlerinin olduğunu
  • Oyun nesnesinin hızını almak için Velocity değişkeninin olduğunu
  • Oyun nesnesinin ekranda kapladığı alanı bulmak için TextureRectangle özelliğinin olduğunu görürüz.

GameObject sınıfının constructor‘ı sadece bir Texture2D nesnesi alıyor ve bu parametreyi kendi iç değişkenlerinin değerlerini hesaplamada kullanıyor.

Artık GameLoop sınıfımızın class seviyesinde, Top nesnesi için, GameObject sınıfından değişken oluşturabiliriz.

public GameObject Top;

LoadContent() methodunda bu değişkenin atamasını yapalım;

Top = new GameObject(Content.Load<Texture2D>("Top"));

Update() methodunda Top nesnemizin yerini hesaplayalım;

KeyboardState ks = Keyboard.GetState();

if (ks.IsKeyDown(Keys.Left))
    Top.Position.X -= 5;
if (ks.IsKeyDown(Keys.Right))
    Top.Position.X += 5;

Aynı method içerisinde Top nesnemizin dönüş miktarını da hesaplayabiliriz; (Yukarı ve Aşağı tuşlarına basıldıkça 10 derece dönmesini sağlayacağız)

if (ks.IsKeyDown(Keys.Up))
    Top.Rotation += MathHelper.ToRadians(10);
if (ks.IsKeyDown(Keys.Down))
    Top.Rotation -= MathHelper.ToRadians(10);

MathHelper sınıfının static ToRadians fonksiyonu sayesinde, Top’umuzun dönme açısını radian cinsinden kolaylıkla hesaplayabiliyoruz.

Top‘umuzun dönme açısının -90 ile +90 dereceler arasında olduğundan ve ekrandan dışarı çıkmayıp, görünür olduğundan emin olalım;

if (Top.Position.X < 0)
    Top.Position.X = 0;
if (Top.Position.X > PENCERE_GENISLIK)
    Top.Position.X = PENCERE_GENISLIK;

if (Top.Rotation > MathHelper.ToRadians(90))
    Top.Rotation = MathHelper.ToRadians(90);
if (Top.Rotation < MathHelper.ToRadians(-90))
    Top.Rotation = MathHelper.ToRadians(-90);

Oyunun, Windows’ta başka bir pencereye geçilmesi esnasında (focus kaybetme) bekleme moduna geçmesini, tekrar oyuna dönüldüğünde ise (focus alma), kaldığı yerden devam etmesini sağlayalım;

Öncelikle sınıf seviyesindeki değişkenlerimize,

</pre><pre class="brush:csharp">bool OYUN_DEVAM_EDIYOR = true;</pre>

ekliyoruz. Microsoft.Xna.Framework.Game sınıfından türetildiği için GameLoop sınıfının OnActivated ve OnDeactivated method’larını override edebiliriz.

OnDeactivated method’unda, oyun penceresinin focus kaybettiğini, OnActivated method’unda ise, oyun penceresinin focus aldığını anlayabiliriz.

protected override void OnActivated(object sender, EventArgs args)
{
  OYUN_DEVAM_EDIYOR = true;
  ArkaplanSes.Resume();
  base.OnActivated(sender, args);
}

protected override void OnDeactivated(object sender, EventArgs args)
{
  OYUN_DEVAM_EDIYOR = false;
  ArkaplanSes.Pause();
  base.OnDeactivated(sender, args);
}


Şu ana kadar oyunumuza hiç düşman eklemedik. Bir sonraki yazımda düşmanları ekleyeceğiz.

*Top'umuzla da düşmanları vurup, puan kazanıyor olacağız.*

Sql Server 2008 Except ve Intersect Anahtar Kelimeleri

Sql Server 2008, T-SQL diline yapılmış birkaç ek geliştirme ile birlikte geldi. Daha önce yazdığım şu makaleden SQL Server 2008 MERGE operatörü hakkında bilgi alabilirsiniz.

Bugün yazacağım yazı ile EXCEPT ve INTERSECT operatörlerini inceleyeceğim.

Hem EXCEPT, hem de INTERSECT operatörü iki farklı sorgunun karşılaştırılması ve bir sonuç kümesi döndürülmesi ilkesi ile çalışır.

t-sql intersect ve except

EXCEPT anahtar kelimesi ile, bir sorgunun sonuç kümesinde olan, fakat diğer sorgunun sonuç kümesinde kesinlikle olmayan kayıtları buluruz.

TABLO1’de bulunup, TABLO2’de bulunmayan kayıtlar

SELECT * FROM TABLO1 EXCEPT SELECT * FROM TABLO2</pre>

TABLO2’de bulunup, TABLO1’de bulunmayan kayıtlar

SELECT * FROM TABLO2
EXCEPT
SELECT * FROM TABLO1

INTERSECT anahtar kelimesi ile ise, her iki sorgunun sonuç kümesinde de kesinlikle olan kayıtları bulabiliriz.

Hem TABLO1’de bulunup, hem de TABLO2’de bulunan kayıtlar

SELECT * FROM TABLO1
INTERSECT
SELECT * FROM TABLO2

Bir örnek ile daha iyi anlaşılacak. Öncelikle Personel ve Stajer tablolarımızı oluşturalım.

CREATE TABLE dbo.Personel
(
    ID INT NOT NULL IDENTITY,
    AdSoyad VARCHAR(100) NOT NULL,
    SicilNo CHAR(6) NOT NULL,
    EMail VARCHAR(100) NOT NULL,
    IseGirisTarihi SMALLDATETIME NOT NULL,
    YoneticiID INT NOT NULL,
    DepartmanID NOT NULL
)
CREATE TABLE dbo.Stajer
(
    ID INT NOT NULL IDENTITY,
    AdSoyad VARCHAR(100) NOT NULL,
    StajerNo CHAR(6) NOT NULL,
    EMail VARCHAR(100) NOT NULL,
    StajBaslangicTarihi SMALLDATETIME NOT NULL,
    YoneticiID INT NOT NULL,
    StajDepartmanID NOT NULL
)

İlk olarak, staj yapmamış personel’in adını seçeceğimiz sorguyu yazalım;

SELECT AdSoyad FROM dbo.Personel
EXCEPT
SELECT AdSoyad FROM dbo.Stajer

İkinci olarak, işe başlamamış olan stajer’lerin adını seçeceğimiz sorguyu yazalım;

SELECT AdSoyad FROM dbo.Stajer
EXCEPT
SELECT AdSoyad FROM dbo.Personel

Son olarak, hem staj yapıp, hem de işe başlamış olan personel’in adını seçeceğimiz sorguyu yazalım;

SELECT AdSoyad FROM dbo.Personel
INTERSECT
SELECT AdSoyad FROM dbo.Stajer


C# method overload nedir?

Method Overload, aynı isme sahip birden fazla method’un olabilmesidir diyebiliriz.

Kural olarak, overload edilmiş method‘lar aynı imza‘ya (signature) sahip olamazlar.

Method İmzası (Method Signature), method’un ismi ve aldığı parametrelerin tipleri/adedidir. Method imzasına, method’un dönüş tipi dahil değildir.

Örnek olarak;

void Topla(int Sayi1, int Sayi2) /// Topla(int, int) { }

void Topla(string Isim1, string Isim2) /// Topla(string, string) { }

/// Aşağıdaki method, ilk Topla method’u ile aynı imzaya sahip void Topla(int Rakam1, int Rakam2) /// Topla(int, int) { }</pre>

Farklı bir örnek;

void EMailGonder(string To, string CC, string Konu, string Mesaj)
{
}

EMailGonder() method‘unu kullanarak, email gönderme işlevini yerine getirebiliriz.

Tek bir alıcı yerine, To kısmının string dizisi (string[]) olması gerektiği durumda, yeni bir method yazmamız, hangi method’u kullanmamız gerektiği konusunda kafa karışıklığına sebep olacaktır.

Method Overload sayesinde, bu kafa karışıklığı ve kod kalabalığından kurtulabiliriz;

void EMailGonder(string[] To, string CC, string Konu, string Mesaj)
{
}

İki method’umuz birlikte;

void EMailGonder(string To, string CC, string Konu, string Mesaj)
{
}

void EMailGonder(string[] To, string CC, string Konu, string Mesaj)
{
}

Artık, EMailGonder() method’unu kullanacağımız zaman, ilk parametreyi string dizisi (string[]) şeklinde verirsek,

void EMailGonder(string[], string, string, string)

imzasına sahip method, ilk parametreyi string olarak verirsek,

void EMailGonder(string, string, string, string)


imzasına sahip olan method çalıştırılacaktır.

Engin Polat hakkında

Senior Software Engineer, @Microsoft

Ada ve Ege'nin babası ;)

Kategoriler

İstatistik

Makale Adedi: 484

Creative Commons Lisansı