文章目錄
- 前言
- 面試題目(只記錄了還記得的部分)
- 一.簡單說下.NETCORE的生命周期?
- 二.C#如何保證在并發情況下接口不會被重復觸發?
- 三.引用類型和值類型有什么區別?
- 四.那怎樣能讓引用類型和值類型一樣,在賦值的時候創建新的數據?(在更改新的引用類型對象b的時候,不影響原來的引用類型對象a)
- 五.C#獲取接口響應時間。
- 六.需要所有接口都這樣寫一次嗎?可以統一獲取接口響應時間嗎?
- 七.接口的異常捕捉。
- 八..NETCORE注冊如何注冊并使用Session?
- 九.數據庫如何實現事務隔離?
- 十.聚集索引和非聚集索引。
- 總結
前言
公司近期工作制度不合理,跟管理層反映無果后,就有了跳槽的打算,于是開始尋找新的機會,參加了一家中級.NET開發工程師的面試。
面試題目(只記錄了還記得的部分)
一.簡單說下.NETCORE的生命周期?
1.文言一心版回答:
.NET Core應用程序的生命周期通常從創建應用程序的主入口點開始,隨后是初始化應用程序,配置服務,建立請求管道,以處理每個HTTP請求。在請求處理完畢后,應用程序會關閉。
2.ChatAI3.5版回答:
在.NET Core 應用程序中,有以下幾個主要的生命周期階段:
a.啟動階段(Bootstrap):在這個階段,應用程序會進行一些初始化操作,比如加載配置,注冊服務,設置日志等。
b.運行時階段(Runtime):在這個階段,應用程序正式開始執行業務邏輯,處理請求等操作。
c.關閉階段(Shutdown):在應用程序即將停止運行時,會執行一些清理操作,釋放資源等。
在這些階段中,可以通過事件來監聽應用程序的狀態變化,以便在合適的時機執行相應的操作。比如可以使用以下事件:
ApplicationStarted:應用程序啟動時觸發。
ApplicationStopping:應用程序即將停止時觸發。
ApplicationStopped:應用程序已經停止時觸發。
通過監聽這些事件,可以在不同階段執行相應的代碼,以實現更精細的控制和管理應用程序的生命周期。
3.博客園某博主的相關回答:
.NetCore 依賴注入的三個生命周期理解:
AddTransient瞬時模式:每次請求,都獲取一個新的實例。即使同一個請求獲取多次也會是不同的實例(注意這里的獲取多次對象是指通過上下文獲取對象,而不是共用上一個對象)
AddScoped:每次請求都獲取一個新的實例。同一個請求獲取多次會得到相同的實例。
AddSingleton單例模式:每次都獲取同一個實例。
二.C#如何保證在并發情況下接口不會被重復觸發?
1.接口在都是同步代碼的情況下,我會使用lock語句塊對代碼進行加鎖。
2.接口在存在異步代碼的情況下,我會使用Semaphore或者SemaphoreSlim,通過信息量控制接口線程保證接口不會被重復觸發。
3.通過redis鎖的方式,保證單據的唯一性。
4.通過數據庫鎖的方式,使用WITH(TABLOCK,HOLDLOCK)選項來獲取表級別的排它鎖,或者使用WITH(UPDLOCKL,ROWLOCK)選項來獲取行級別的排它鎖,從而控制對數據庫對象的并發訪問。
三.引用類型和值類型有什么區別?
1.引用類型:
a.變量存儲對象的引用(內存地址),實際數據存儲在堆上。
b.引用類型的變量指向實際的對象,對變量賦值只復制引用,不復制整個對象(比如說a對象賦值給b對象,當我們對b對象進行更改的時候,a對象也會跟著改變,因為他們實際上是指向同一個內存地址,值從始至終都只有一個)
c.常用的引用類型有:類(Class),接口(Interface),委托(Delegate),字符串(string),數組(Array)等
2.值類型:
a.變量直接包含數據,存儲在棧中
b.值類型賦值會直接復制一個新的數據(比如說a賦值給b,就會在b那復制一份新的數據,對b進行任何操作都不影響a)
c.常用的值類型有:整數類型(int,long,short,byte),浮點數類型(float,double,decimal),字符類型(char),布爾類型(bool),結構體(struct),枚舉(enum),int?,DateTime?(問號表示值可以為null)等
四.那怎樣能讓引用類型和值類型一樣,在賦值的時候創建新的數據?(在更改新的引用類型對象b的時候,不影響原來的引用類型對象a)
ChatAI3.5回答:
1.深拷貝(Deep Copy):對于自定義的引用類型,可以在對象內部實現深拷貝邏輯;即創建一個新的對象,將原始對象的數據賦值到新對象中。這樣,在對新的對象進行修改時不會影響初始對象。
2.使用特定的復制方法:對于一些標準的引用類型,比如說字符串和數組,就可以使用string.Copy()和Array.Copy()方法來創建新的對象。
個人補充:
1.C#在方法調用參數的時候,參數類型前面可以加ref或者in關鍵字;
其中ref關鍵字會讓任何傳遞過來的參數當作引用類型處理(即在方法中變更參數,傳入方法中的值參數也會被當作引用類型處理,同步發生改變)
而in關鍵,會將傳遞過來的參數視為只讀,這樣就避免了在方法內部對參數進行修改。
2.C#可以通過序列化,反序列化生成一個新的引用類型,不影響初始引用對象。
五.C#獲取接口響應時間。
ChatAI3.5回答:
1.使用Stopwatch對象,使用stopwatch.Start()方法和stopwatch.Stop()方法分別置于接口請求前后,而后通過stopwatch.Elapsed屬性獲取接口響應時間。
2.接口請求前后分別使用DateTimeOffset.UtcNow.ToUnixTimeSeconds()獲取當前服務器的時間戳值,通過兩個時間戳的差值得到接口響應時間。
六.需要所有接口都這樣寫一次嗎?可以統一獲取接口響應時間嗎?
ChatAI3.5回答:
1.在C#中,可以通過創建一個統一的HTTP客戶端類來封裝發送HTTP請求的邏輯,并在其中實現統一計算接口請求消耗時間的功能。這樣可以避免每個接口單獨計算請求消耗時間的重復操作。
代碼案例如下:
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;public class CustomHttpClient
{private HttpClient _httpClient;public CustomHttpClient(){_httpClient = new HttpClient();}public async Task<string> GetResponseTimeAsync(string url){var stopwatch = new Stopwatch();stopwatch.Start()HttpResponseMessage response = await _httpClient.GetAsync(url);stopwatch.Stop();TimeSpan elapsed = stopwatch.Elapsed;return $"接口響應時間為:{elapsed.TotalMilliseconds}ms";}
}
七.接口的異常捕捉。
ChatAI3.5回答:
在C#中,你可以通過自定義Action Filter來實現用戶請求接口異常時記錄異常信息,請求參數等功能。Action Filter是ASP.NET Core中一種常用的過濾器,可以用來在執行控制器中的Action前后執行一些邏輯,列入日志記錄,異常處理等操作。
下面是一種簡單的示例,演示了如何在ASP.NET Core 中實現一個自定義Action Filter來記錄異常信息和請求參數:
首先,定義一個自定的Action Filter類,繼承IActionFilter接口:
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;public class CustomActionFilter : IActionFilter{private readonly ILogger<CustomActionFilter> _logger;public CustomActionFilter(ILogger<CustomActionFilter> logger){_logger = logger;}public void OnActionExecting(ActionExecutingContext context){//在執行Action前記錄請求參數var parameters = context.ActionArguments;_logger.LogInformation("Request Parameters:{@parmeters}",parameters);}public void OnActionExecuted(ActionExecutedContext context){//在執行Action后記錄異常信息if(context.Exception != null){_logger.logError(context.Exception,"An error occurred while processing the request.");}}
}
然后,在Starup.cs中注冊該Aciton Filter;
using Microsoft.Extensions.DependencyInjection;public class Startup{public void ConfigureServices(IServericeCollection services){services.AddControllers(options => {option.Filters.Add<CustomActionFilter>();});//添加其他服務配置}
}
在上述案例中,我們定義了一個 CustomActionFilter類來實現自定一個的Action Filter功能,其中在OnActionExecuting方法中記錄請求參數,在OnActionExecuted方法中記錄異常信息。然后在Startup.cs中通過options.Filters.Add()注冊該Action Filter。
通過這種方式,當用戶請求接口發生異常,Action Filter會自動捕捉并記錄異常信息,請求參數等,方便后續排查問題和分析。
八…NETCORE注冊如何注冊并使用Session?
ChatAI3.5回答:
在Asp.NET Core中,你可以通過AddSession方法來注冊并配置Session功能。下面是一個簡單的示例。
首先,在Startup.cs的ConfigureServices方法中進行注冊和配置:
public class Startup{public void ConfigureServices(IServiceCollection services){//其他服務配置services.AddSession(options=>{options.IdleTImeout = TimeSpan.FromMinutes(20);options.Cookie.HttpOnly = true;options.Cooie.IsEssential = true;});//其他服務配置}public void Configure(IApplicationBuilder app,IWebHostEnvironment env){//其他中間件配置app.UseSession();//其他中間件配置}
}
在上述案例中,我們功過services.AddSession()方法注冊了Session功能,并且配置了Session的超時時間,Cookie特性等。然后在Configure方法中使用app.UseSession()啟用了Session中間件。
接下來,可以在控制器或者Razor頁面中使用HttpContext.Session屬性來訪問和操作Session數據,例如:
public class HomeController:Controller{public IActionResult Index(){HttpContext.Session.SetString("UserName","Joker");var userName = HttpContext.Session.GetString("UserName");return View();}
}
上述案例中,通過HttpContext.Session.SetString()方法存儲Session值,HttpContext.Session.GetString()方法獲取對應的Session值
九.數據庫如何實現事務隔離?
數據庫可以通過加鎖來實現事務隔離,常見的鎖有行級鎖,表級鎖,頁級鎖等。這些鎖可以用于實現不同的事務隔離級別,例如可重復讀和串行化級別。比如:
1.行級鎖:行級鎖是對數據庫中的行進行加鎖,當一個事務要訪問某一行數據時,會獲取該行的鎖,其他事務無法修改該行知道鎖被釋放。行及鎖可以實現較高的并發性和靈活性;sqlserver常見的行級鎖有:共享鎖(Shared Lock),排他鎖(Exclusive Lock)
2.表級鎖:表級鎖時對整個表進行加鎖,當一個事務要訪問表中的數據時,會獲取整個表的鎖,其他事務無法修改表中的數據知道鎖被釋放。表級鎖通常用于較低級別的隔離要求,因為它限制了其他事務對表的訪問;sqlserver常見的表級鎖有:表共享鎖(table shared lock),表排它鎖(table exclusive lock)
3.頁級鎖:頁級鎖時對數據庫中的頁(通常是連續的數據塊)進行加鎖,當一個事務需要訪問某一頁數據時,會獲取該頁的鎖,其他事務無法修改該頁中的數據知道鎖被釋放。頁級鎖介于行級鎖和表級鎖之間,可以在一定程度上平衡并發性能和隔離級別要求;sqlserver常見的頁級鎖有:頁共享鎖(page shared lock),頁排它鎖(page exclusive lock)
4.sqlserver還提供了其他類型的鎖,比如 意向鎖(intent lock),更新鎖(update lock),行版本鎖(row versioning locks)等,用于支持不同的并發控制需求
十.聚集索引和非聚集索引。
sqlserver中的聚集索引和非聚集索引是數據庫中常用的兩種索引類型,他們在數據庫查詢性能優化和數據存儲方面起到重要作用。
1.聚集索引(Clustered Index):
a. 定義:聚集索引確定了表中數據的物理排序順序,并且葉子節點包含實際的數據行。
b.特點:每張表只有一個聚集索引,它決定了表中數據的物理存儲順序,因此表中的數據按照聚集索引的順序進行存儲。
c.優勢:通過聚集索引可以快速查詢范圍內的數據,因為數據行在物理上相鄰,適合范圍查詢和排序。
d.適用場景:適用于經常按照某列進行范圍查找和排序的字段。
2.非聚集索引(Non-Clustered Index):
a.定義:非聚集索引中葉子節點并不包含實際的數據行,而是包含指向實際數據行的指針。
b.特點:一張表可以擁有多個非聚集索引,他們并不影響表中數據的物理存儲順序,而是在索引中維護指向實際數據行的引用。
c.優勢:通過非聚集索引可以快速定位到需要的記錄,適合于單值查詢和覆蓋索引。
d.適用場景:適合于經常要進行單值查詢的字段,例如where子句中的條件字段。
總結
總的來說,這是一場很失敗的面試經歷,吃一塹長一智,再接再厲。