C# derleyicisi tarafından yorumlanan null durum statik analizi öznitelikleri
Null atanabilir bir bağlamda, derleyici tüm başvuru türü değişkenlerinin null durumunu belirlemek için kodun statik analizini gerçekleştirir:
- not-null: Statik çözümleme, bir değişkenin null olmayan bir değere sahip olduğunu belirler.
- belki-null: Statik analiz, bir değişkene null olmayan bir değer atandığını belirleyemez.
Bu durumlar, bir null değer oluşturarak başvuruda bulunabileceğiniz durumlarda derleyicinin uyarılar sağlamasına System.NullReferenceExceptionolanak tanır. Bu öznitelikler derleyiciye bağımsız değişkenlerin null durumu , dönüş değerleri ve bağımsız değişkenlerin ve dönüş değerlerinin durumuna göre nesne üyeleri hakkında anlamsal bilgiler sağlar. API'leriniz bu anlamsal bilgilerle düzgün bir şekilde eklendiğinde derleyici daha doğru uyarılar sağlar.
Bu makalede, null atanabilir başvuru türü özniteliklerinin her biri ve bunların nasıl kullanılacağı hakkında kısa bir açıklama sağlanır.
Bir örnekle başlayalım. Kitaplığınızın bir kaynak dizesini almak için aşağıdaki API'ye sahip olduğunu düşünün. Bu yöntem başlangıçta null değer atanabilir bir belirsiz bağlamda derlendi:
bool TryGetMessage(string key, out string message)
{
if (_messageMap.ContainsKey(key))
message = _messageMap[key];
else
message = null;
return message != null;
}
Yukarıdaki örnek, .NET'teki tanıdık Try*
deseni izler. Bu API için iki başvuru parametresi vardır: key
ve message
. Bu API, bu parametrelerin null durumuyla ilgili olarak aşağıdaki kurallara sahiptir:
- Arayanlar için
key
bağımsız değişken olarak geçmemelidirnull
. - Çağıranlar, değeri için
message
bağımsız değişken olarak olannull
bir değişken geçirebilir. TryGetMessage
yöntemi döndürürsetrue
değerimessage
null değildir. Dönüş değeri isefalse
değerimessage
null olur.
için key
kuralı kısa olarak ifade edilebilir: key
null atanamaz bir başvuru türü olmalıdır. message
parametresi daha karmaşıktır. Bağımsız değişken olarak bir değişkene null
izin verir, ancak başarılı olduğunda bağımsız değişkenin out
olmadığını null
garanti eder. Bu senaryolarda, beklentileri açıklamak için daha zengin bir kelime dağarcığına ihtiyacınız vardır. NotNullWhen
Aşağıda açıklanan özniteliği, parametre için message
kullanılan bağımsız değişkenin null durumunu açıklar.
Not
Bu özniteliklerin eklenmesi, derleyiciye API'nizin kuralları hakkında daha fazla bilgi verir. Çağıran kod null atanabilir bir bağlamda derlenirken, derleyici bu kuralları ihlal ettiğinde çağıranları uyarır. Bu öznitelikler, uygulamanız üzerinde daha fazla denetime olanak sağlamaz.
Öznitelik | Kategori | Anlamı |
---|---|---|
AllowNull | Ön koşul | Null değer atanamayan bir parametre, alan veya özellik null olabilir. |
İzin Verme | Ön koşul | Null atanabilir parametre, alan veya özellik hiçbir zaman null olmamalıdır. |
BelkiNull | Son koşul | Null değer atanamayan parametre, alan, özellik veya dönüş değeri null olabilir. |
NotNull | Son koşul | Null atanabilir parametre, alan, özellik veya dönüş değeri hiçbir zaman null olmaz. |
BelkiNullWhen | Koşullu son koşul | Yöntem belirtilen bool değeri döndürdüğünde null değer atanamayan bir bağımsız değişken null olabilir. |
NotNullWhen | Koşullu son koşul | Yöntem belirtilen bool değeri döndürdüğünde null atanabilir bağımsız değişken null olmaz. |
NotNullIfNotNull | Koşullu son koşul | Belirtilen parametrenin bağımsız değişkeni null değilse, dönüş değeri, özellik veya bağımsız değişken null değildir. |
MemberNotNull | Yöntem ve özellik yardımcı yöntemleri | Yöntem döndürdüğünde listelenen üye null olmaz. |
MemberNotNullWhen | Yöntem ve özellik yardımcı yöntemleri | Yöntem belirtilen bool değeri döndürdüğünde listelenen üye null olmaz. |
DoNotReturn | Ulaşılamayan kod | Yöntem veya özellik hiçbir zaman döndürmez. Başka bir deyişle, her zaman bir özel durum oluşturur. |
DoNotReturnIf | Ulaşılamayan kod | bu yöntem veya özellik, ilişkili bool parametre belirtilen değere sahipse hiçbir zaman döndürmez. |
Yukarıdaki açıklamalar, her özniteliğin ne yaptığına yönelik hızlı başvurulardır. Aşağıdaki bölümlerde bu özniteliklerin davranışı ve anlamı daha ayrıntılı bir şekilde açıklanmaktadır.
Önkoşullar: AllowNull
ve DisallowNull
Makul bir varsayılan değere sahip olduğundan hiçbir zaman döndürülmeyecek null
bir okuma/yazma özelliği düşünün. Arayanlar, bu varsayılan değere ayarlarken ayarlanan erişimciye geçer null
. Örneğin, sohbet odasında ekran adı isteyen bir mesajlaşma sistemini düşünün. Hiçbiri sağlanmazsa sistem rastgele bir ad oluşturur:
public string ScreenName
{
get => _screenName;
set => _screenName = value ?? GenerateRandomScreenName();
}
private string _screenName;
Yukarıdaki kodu boş değer atanabilir, belirsiz bir bağlamda derlediğinizde her şey yolunda demektir. Null atanabilir başvuru türlerini etkinleştirdiğinizde, ScreenName
özellik null atanamaz bir başvuruya dönüşür. Erişimci için get
bu doğrudur: hiçbir zaman döndürmez null
. Arayanların için döndürülen özelliği null
denetlemesi gerekmez. Ancak şimdi özelliğini bir uyarı oluşturacak şekilde null
ayarlamak. Bu kod türünü desteklemek için özniteliğini System.Diagnostics.CodeAnalysis.AllowNullAttribute aşağıdaki kodda gösterildiği gibi özelliğine eklersiniz:
[AllowNull]
public string ScreenName
{
get => _screenName;
set => _screenName = value ?? GenerateRandomScreenName();
}
private string _screenName = GenerateRandomScreenName();
Bu ve bu makalede ele alınan diğer öznitelikleri kullanmak için için System.Diagnostics.CodeAnalysis bir using
yönerge eklemeniz gerekebilir. özniteliği, erişimciye değil özelliğine set
uygulanır. AllowNull
özniteliği ön koşulları belirtir ve yalnızca bağımsız değişkenler için geçerlidir. Erişimcinin get
bir dönüş değeri vardır, ancak parametresi yoktur. Bu nedenle, AllowNull
özniteliği yalnızca erişimci set
için geçerlidir.
Yukarıdaki örnekte, bir bağımsız değişkene özniteliği eklenirken nelerin aranacakları AllowNull
gösterilmektedir:
- Bu değişkenin genel sözleşmesi olmaması gerektiğidir
null
, bu nedenle null atanamaz bir başvuru türü istiyorsunuz. - Bir çağıranın bağımsız değişken olarak geçmesine
null
yönelik senaryolar vardır, ancak bunlar en yaygın kullanım değildir.
Genellikle özellikler veya in
, out
ve ref
bağımsız değişkenleri için bu özniteliğe ihtiyacınız olur. Bir AllowNull
değişken genellikle null olmadığında özniteliği en iyi seçenektir, ancak önkoşul olarak izin null
vermeniz gerekir.
kullanma DisallowNull
senaryolarıyla karşıtlık: Bu özniteliği, null atanabilir başvuru türünün bağımsız değişkeninin olmaması null
gerektiğini belirtmek için kullanırsınız. Varsayılan değer olan null
ancak istemcilerin bunu yalnızca null olmayan bir değere ayarlayabildiği bir özellik düşünün. Aşağıdaki kodu inceleyin:
public string ReviewComment
{
get => _comment;
set => _comment = value ?? throw new ArgumentNullException(nameof(value), "Cannot set to null");
}
string _comment;
Yukarıdaki kod, tasarımınızı ReviewComment
ifade etmenin en iyi yoludur null
ve olarak ayarlanamaz null
. Bu kod null atanabilir duruma geldikten sonra, bu kavramı kullanarak System.Diagnostics.CodeAnalysis.DisallowNullAttributeçağıranlara daha net bir şekilde ifade edebilirsiniz:
[DisallowNull]
public string? ReviewComment
{
get => _comment;
set => _comment = value ?? throw new ArgumentNullException(nameof(value), "Cannot set to null");
}
string? _comment;
Boş değer atanabilir bir bağlamda erişimci ReviewComment
get
varsayılan değerini null
döndürebilir. Derleyici, erişimden önce denetlenilmesi gerektiği konusunda uyarır. Ayrıca, çağıranları, olsa null
bile çağıranların açıkça olarak olarak ayarlamaması gerektiği konusunda uyarır null
. DisallowNull
Özniteliği ayrıca bir ön koşul belirtir, erişimciyi get
etkilemez. Şu özellikleri gözlemlerken özniteliğini DisallowNull
kullanırsınız:
- Değişken, genellikle ilk kez örneklendiğinde temel senaryolarda olabilir
null
. - değişkeni açıkça olarak
null
ayarlanmalıdır.
Bu durumlar başlangıçta null olan bir kodda yaygındır. Nesne özellikleri iki ayrı başlatma işleminde ayarlanmış olabilir. Bazı özellikler yalnızca zaman uyumsuz bir çalışma tamamlandıktan sonra ayarlanmış olabilir.
AllowNull
ve DisallowNull
öznitelikleri, değişkenlerdeki önkoşulların bu değişkenlerdeki null atanabilir ek açıklamalarla eşleşmeyebileceğini belirtmenizi sağlar. Bunlar API'nizin özellikleri hakkında daha fazla ayrıntı sağlar. Bu ek bilgiler, çağıranların API'nizi doğru kullanmalarını sağlar. Aşağıdaki öznitelikleri kullanarak önkoşulları belirttiğinizi unutmayın:
- AllowNull: Null değer atanamayan bir bağımsız değişken null olabilir.
- DisallowNull: Boş değer atanabilir bağımsız değişken hiçbir zaman null olmamalıdır.
Son koşul: MaybeNull
ve NotNull
Aşağıdaki imzaya sahip bir yönteminiz olduğunu varsayalım:
public Customer FindCustomer(string lastName, string firstName)
Aranan ad bulunamadığında döndürülmesi null
için büyük olasılıkla bunun gibi bir yöntem yazdınız. açıkça null
kaydın bulunamadığını gösteriyor. Bu örnekte, büyük olasılıkla dönüş türünü olarak Customer
Customer?
değiştirirsiniz. Dönüş değerinin null atanabilir başvuru türü olarak bildirilmesi, bu API'nin amacını açıkça belirtir:
public Customer? FindCustomer(string lastName, string firstName)
Genel değerler null atanabilirliği altında ele alınan nedenlerden dolayı bu teknik API'nizle eşleşen statik analizi üretmeyebilir. Benzer bir desene göre genel bir yönteminiz olabilir:
public T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate)
yöntemi aranan öğe bulunamadığında döndürür null
. Yöntemin, bir öğe bulunamadığında döndürdüğünü null
, yöntemin dönüş ek MaybeNull
açıklamasını ekleyerek netleştirebilirsiniz:
[return: MaybeNull]
public T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate)
Yukarıdaki kod, çağıranlara dönüş değerinin aslında null olabileceğini bildirir. Ayrıca, türü null atanamaz olsa bile yönteminin bir null
ifade döndürebileceğini derleyiciye bildirir. tür parametresinin bir örneğini döndüren genel bir yönteminiz olduğunda, T
özniteliğini kullanarak NotNull
hiçbir zaman döndürmediğini null
ifade edebilirsiniz.
Ayrıca, tür null atanabilir bir başvuru türü olsa bile bir dönüş değerinin veya bağımsız değişkenin null olmadığını belirtebilirsiniz. Aşağıdaki yöntem, ilk bağımsız değişkeni ise oluşturan bir yardımcı yöntemdir null
:
public static void ThrowWhenNull(object value, string valueExpression = "")
{
if (value is null) throw new ArgumentNullException(nameof(value), valueExpression);
}
Bu yordamı aşağıdaki gibi çağırabilirsiniz:
public static void LogMessage(string? message)
{
ThrowWhenNull(message, $"{nameof(message)} must not be null");
Console.WriteLine(message.Length);
}
Null başvuru türlerini etkinleştirdikten sonra, önceki kodun uyarı olmadan derlendiğinden emin olmak istiyorsunuz. Yöntemi döndürdüğünde parametresinin value
null olmaması garanti edilir. Ancak null başvuruyla çağrı ThrowWhenNull
yapmak kabul edilebilir. Null atanabilir bir başvuru türü oluşturabilir value
ve parametre bildirimine son koşulu ekleyebilirsiniz NotNull
:
public static void ThrowWhenNull([NotNull] object? value, string valueExpression = "")
{
_ = value ?? throw new ArgumentNullException(nameof(value), valueExpression);
// other logic elided
Yukarıdaki kod mevcut sözleşmeyi açıkça ifade eder: Çağıranlar değeriyle null
bir değişken geçirebilir, ancak yöntem özel durum oluşturmadan döndürürse bağımsız değişkenin hiçbir zaman null olmadığı garanti edilir.
Aşağıdaki öznitelikleri kullanarak koşulsuz son koşul belirtirsiniz:
- MaybeNull: Null değer atanamayan bir dönüş değeri null olabilir.
- NotNull: Null değer atanabilir dönüş değeri hiçbir zaman null olmaz.
Koşullu son koşullar: NotNullWhen
, MaybeNullWhen
ve NotNullIfNotNull
yöntemine string
String.IsNullOrEmpty(String)aşinasınızdır. Bu yöntem, bağımsız değişken null veya boş bir dize olduğunda döndürür true
. Bu bir null-check biçimidir: Yönteminin döndürdüğünde false
çağıranların bağımsız değişkeni null olarak denetlemesi gerekmez. Bunun gibi bir yöntemi null atanabilir duruma getirmek için bağımsız değişkenini null atanabilir bir başvuru türüne ayarlar ve özniteliğini NotNullWhen
eklersiniz:
bool IsNullOrEmpty([NotNullWhen(false)] string? value)
Bu, derleyiciye dönüş değerinin false
null denetimlere gerek olmadığı herhangi bir kodu bildirir. özniteliğinin eklenmesi, derleyicinin gerekli null denetimini gerçekleştiren statik çözümlemesini IsNullOrEmpty
bildirir: döndürdüğünde false
bağımsız değişken değildir null
.
string? userInput = GetUserInput();
if (!string.IsNullOrEmpty(userInput))
{
int messageLength = userInput.Length; // no null check needed.
}
// null check needed on userInput here.
. String.IsNullOrEmpty(String) NET Core 3.0 için yukarıda gösterildiği gibi yönteme ek açıklama eklenecektir. Kod tabanınızda nesnelerin null değerlerin durumunu denetleyebilen benzer yöntemleriniz olabilir. Derleyici özel null denetim yöntemlerini tanımaz ve ek açıklamaları kendiniz eklemeniz gerekir. özniteliğini eklediğinizde, derleyicinin statik analizi test edilen değişkenin null olarak denetlendiğini bilir.
Bu öznitelikler için başka bir kullanım düzenidir Try*
. ve out
bağımsız değişkenleri için ref
son koşul, dönüş değeri üzerinden iletilir. Daha önce gösterilen bu yöntemi göz önünde bulundurun (null atanabilir devre dışı bırakılmış bir bağlamda):
bool TryGetMessage(string key, out string message)
{
if (_messageMap.ContainsKey(key))
message = _messageMap[key];
else
message = null;
return message != null;
}
Yukarıdaki yöntem tipik bir .NET deyimini izler: dönüş değeri, bulunan değere ayarlandığını veya ileti bulunamazsa varsayılan değere ayarlandığını gösterir message
. yöntemi döndürürse true
değeri message
null değildir; aksi takdirde yöntemi null olarak ayarlanır message
.
Null değer atanabilir bir etkinleştirilmiş bağlamda, özniteliğini NotNullWhen
kullanarak bu deyimi iletebilirsiniz. Null atanabilir başvuru türleri için parametrelere açıklama eklediğinizde, bir string?
yapın message
ve bir öznitelik ekleyin:
bool TryGetMessage(string key, [NotNullWhen(true)] out string? message)
{
if (_messageMap.ContainsKey(key))
message = _messageMap[key];
else
message = null;
return message is not null;
}
Yukarıdaki örnekte değerinin message
döndürdüğünde TryGetMessage
true
null olmadığı bilinmektedir. Kod tabanınızda benzer yöntemlere aynı şekilde açıklama eklemelisiniz: bağımsız değişkenler eşit null
olabilir ve yöntemi döndürdüğünde true
null olmadığı bilinmektedir.
Ayrıca ihtiyacınız olabilecek son bir öznitelik vardır. Bazen bir dönüş değerinin null durumu bir veya daha fazla bağımsız değişkenin null durumuna bağlıdır. Bu yöntemler, belirli bağımsız değişkenler null
olmadığından null olmayan bir değer döndürür. Bu yöntemlere doğru not eklemek için özniteliğini NotNullIfNotNull
kullanırsınız. Aşağıdaki yöntemi göz önünde bulundurun:
string GetTopLevelDomainFromFullUrl(string url)
url
Bağımsız değişken null değilse, çıkış değildirnull
. Null atanabilir başvurular etkinleştirildikten sonra, API'niz null bağımsız değişken kabul edebilirse daha fazla ek açıklama eklemeniz gerekir. Aşağıdaki kodda gösterildiği gibi dönüş türüne açıklama ekleyebilirsiniz:
string? GetTopLevelDomainFromFullUrl(string? url)
Bu da işe yarar, ancak genellikle çağıranları ek null
denetimler uygulamaya zorlar. Anlaşma, dönüş değerinin yalnızca bağımsız değişken url
olduğunda olmasıdır.null
null
Bu sözleşmeyi ifade etmek için aşağıdaki kodda gösterildiği gibi bu yönteme açıklama ekleyebilirsiniz:
[return: NotNullIfNotNull(nameof(url))]
string? GetTopLevelDomainFromFullUrl(string? url)
Önceki örnekte parametresi url
için işleci kullanılırnameof
. Bu özellik C# 11'de kullanılabilir. C# 11'in öncesinde parametrenin adını dize olarak yazmanız gerekir. Dönüş değeri ve bağımsız değişkeninin her ikisi de olabilir null
ifadesiyle ?
eklenmiştir. özniteliği, bağımsız değişken null
olmadığında dönüş değerinin null olmayacağına url
dair daha fazla bilgi verir.
Şu öznitelikleri kullanarak koşullu son koşulları belirtirsiniz:
- MaybeNullWhen: Yöntem belirtilen
bool
değeri döndürdüğünde null olmayan bir bağımsız değişken null olabilir. - NotNullWhen: Yöntem belirtilen
bool
değeri döndürdüğünde null değer atanabilir bağımsız değişken null olmaz. - NotNullIfNotNull: Belirtilen parametrenin bağımsız değişkeni null değilse, dönüş değeri null değildir.
Yardımcı yöntemler: MemberNotNull
ve MemberNotNullWhen
Bu öznitelikler, ortak kodu oluşturuculardan yardımcı yöntemlere yeniden düzenlediğinizde amacınızı belirtir. C# derleyicisi oluşturucuları ve alan başlatıcılarını analiz ederek her oluşturucu döndürmeden önce tüm null atanamayan başvuru alanlarının başlatıldığından emin olur. Ancak, C# derleyicisi tüm yardımcı yöntemler aracılığıyla alan atamalarını izlemez. Derleyici, alanlar doğrudan oluşturucuda değil, bir yardımcı yönteminde başlatılmadığında uyarı CS8618
döndürür. yöntemini bir yöntem bildirimine ekler MemberNotNullAttribute ve yönteminde null olmayan bir değere başlatılan alanları belirtirsiniz. Örneğin, aşağıdaki örneği göz önünde bulundurun:
public class Container
{
private string _uniqueIdentifier; // must be initialized.
private string? _optionalMessage;
public Container()
{
Helper();
}
public Container(string message)
{
Helper();
_optionalMessage = message;
}
[MemberNotNull(nameof(_uniqueIdentifier))]
private void Helper()
{
_uniqueIdentifier = DateTime.Now.Ticks.ToString();
}
}
Öznitelik oluşturucusunun MemberNotNull
bağımsız değişkenleri olarak birden çok alan adı belirtebilirsiniz.
bağımsız MemberNotNullWhenAttribute değişkenine sahiptir bool
. Yardımcı yönteminizin, yardımcı yönteminizin alanları başlatıp başlatmadığını belirten bir bool
döndürdüğü durumlarda kullanırsınızMemberNotNullWhen
.
Yöntemin oluşturması çağrıldığında null atanabilir çözümlemeyi durdurma
Genellikle özel durum yardımcıları veya diğer yardımcı program yöntemleri gibi bazı yöntemler her zaman bir özel durum oluşturarak çıkar. Veya bir yardımcı, Boole bağımsız değişkeninin değerine göre bir özel durum oluşturabilir.
İlk durumda, özniteliğini DoesNotReturnAttribute yöntem bildirimine ekleyebilirsiniz. Derleyicinin null durum çözümlemesi, ile DoesNotReturn
ek açıklamalı bir yönteme yapılan çağrıyı izleyen bir yöntemdeki hiçbir kodu denetlemez. Şu yöntemi göz önünde bulundurun:
[DoesNotReturn]
private void FailFast()
{
throw new InvalidOperationException();
}
public void SetState(object containedField)
{
if (containedField is null)
{
FailFast();
}
// containedField can't be null:
_field = containedField;
}
Derleyici, çağrısından FailFast
sonra herhangi bir uyarı vermez.
İkinci durumda özniteliğini yönteminin System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute Boole parametresine eklersiniz. Önceki örneği aşağıdaki gibi değiştirebilirsiniz:
private void FailFastIf([DoesNotReturnIf(true)] bool isNull)
{
if (isNull)
{
throw new InvalidOperationException();
}
}
public void SetFieldState(object? containedField)
{
FailFastIf(containedField == null);
// No warning: containedField can't be null here:
_field = containedField;
}
Bağımsız değişkeninin değeri oluşturucunun DoesNotReturnIf
değeriyle eşleştiğinde, derleyici bu yöntemden sonra null durum analizi gerçekleştirmez.
Özet
Boş değer atanabilir başvuru türleri eklemek, api'lerinizin olabilecek null
değişkenlere yönelik beklentilerini açıklamak için bir ilk sözcük dağarcığı sağlar. Öznitelikler, değişkenlerin null durumunu önkoşullar ve son koşul olarak tanımlamak için daha zengin bir sözlük sağlar. Bu öznitelikler beklentilerinizi daha net bir şekilde açıklar ve API'lerinizi kullanan geliştiriciler için daha iyi bir deneyim sağlar.
Boş değer atanabilir bir bağlam için kitaplıkları güncelleştirirken, API'lerinizin kullanıcılarını doğru kullanıma yönlendirmek için bu öznitelikleri ekleyin. Bu öznitelikler, bağımsız değişkenlerin ve dönüş değerlerinin null durumunu tam olarak açıklamanıza yardımcı olur.
- AllowNull: Null değer atanamayan bir alan, parametre veya özellik null olabilir.
- DisallowNull: Null atanabilir alan, parametre veya özellik hiçbir zaman null olmamalıdır.
- MaybeNull: Null değer atanamayan bir alan, parametre, özellik veya dönüş değeri null olabilir.
- NotNull: Boş değer atanabilir bir alan, parametre, özellik veya dönüş değeri hiçbir zaman null olmaz.
- MaybeNullWhen: Yöntem belirtilen
bool
değeri döndürdüğünde null olmayan bir bağımsız değişken null olabilir. - NotNullWhen: Yöntem belirtilen
bool
değeri döndürdüğünde null değer atanabilir bağımsız değişken null olmaz. - NotNullIfNotNull: Belirtilen parametrenin bağımsız değişkeni null değilse parametre, özellik veya dönüş değeri null değildir.
- DoNotReturn: Bir yöntem veya özellik hiçbir zaman döndürmez. Başka bir deyişle, her zaman bir özel durum oluşturur.
- DoesNotReturnIf: bu yöntem veya özellik, ilişkili
bool
parametre belirtilen değere sahipse hiçbir zaman döndürmez.